You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用pgLoader从SQL Server迁移数据至PostgreSQL时遭遇特殊字符(ñ/í等)编码错误

使用pgLoader从SQL Server迁移数据至PostgreSQL时遭遇特殊字符(ñ/í等)编码错误

看起来你遇到的是典型的编码链条不匹配问题——虽然脚本里指定了编码,但Windows Server环境下的系统编码、SQL Server实际数据编码和pgLoader的解析编码没对齐,导致出现了UTF8字节解析错误。我之前帮朋友解决过类似的Windows Server下pgLoader迁移问题,给你一步步排查和解决的方案:

先拆解错误根源

报错里的BABEL-ENCODINGS:INVALID-UTF8-STARTER-BYTE是关键信号:pgLoader在把SQL Server的编码数据转成PostgreSQL可识别的格式时,遇到了无法解析的字节。虽然你脚本里设了client_encoding = 'WIN1252',但Windows Server的系统默认编码、SQL Server的实际列 collation 可能和你之前的Docker Windows环境不一样。

具体解决步骤

1. 先确认SQL Server的实际数据编码

先查目标表中含特殊字符列的collation(对应实际编码),在SQL Server中执行:

SELECT 
  col.name AS column_name,
  col.collation_name
FROM sys.columns col
JOIN sys.tables tbl ON col.object_id = tbl.object_id
WHERE tbl.name = 'DRecords' 
  AND col.collation_name IS NOT NULL;
  • 如果结果是SQL_Latin1_General_CP1_CI_AS/Modern_Spanish_CI_AS,确实对应WIN1252;
  • 如果是其他collation(比如Chinese_PRC_CI_AS对应GBK),你脚本里的WIN1252就需要改成对应的PostgreSQL编码名(比如GBK)。

2. 调整pgLoader脚本的编码指定逻辑

在连接SQL Server时明确指定读取编码,避免pgLoader自动检测错误,同时在PostgreSQL会话中重复设置编码确保一致:

  • FROM连接串改成:
    FROM mssql://sa:sa@172.22.0.1/ADB?encoding=WIN1252
    
  • client_encoding的设置移到BEFORE LOAD的SQL块里,确保会话生效:
    BEFORE LOAD DO $$
    SET session_replication_role = replica;
    SET client_encoding = 'WIN1252';
    $$
    

3. 先小批量测试+记录错误

先把批量行数改小,加上错误日志,定位具体是哪一行的字符出问题:
WITH参数里添加:

batch rows = 1000,
log errors to 'drecords_load_errors.log'

这样可以看到具体的错误行内容,方便你验证编码是否真的匹配。

4. 适配Windows Server的系统编码

Windows Server的默认控制台编码可能和Windows 10不同,在运行pgLoader之前,先在命令行里执行以下命令,强制设置当前会话的编码:

chcp 1252
set LANG=en_US.WIN1252

再运行pgLoader脚本,避免系统编码干扰pgLoader的解析。

修改后的完整测试脚本

-- 调整后的测试用脚本
LOAD DATABASE
  FROM mssql://sa:sa@172.22.0.1/ADB?encoding=WIN1252
  INTO postgresql://postgres:sa@172.22.0.1/ADB

WITH
  data only, -- 仅复制数据,不修改表结构
  disable triggers,
  no foreign keys,
  quote identifiers,
  batch rows = 1000, -- 小批量测试定位问题
  prefetch rows = 1000,
  log errors to 'drecords_load_errors.log' -- 记录错误行详情

CAST
  type varchar TO text,
  type nvarchar TO text,
  type text TO text

SET
  work_mem to '256MB',
  maintenance_work_mem to '1GB'

ALTER SCHEMA 'dbo' RENAME TO 'public'

INCLUDING ONLY TABLE NAMES LIKE 'DRecords' IN SCHEMA 'dbo'

BEFORE LOAD DO $$
  SET session_replication_role = replica;
  SET client_encoding = 'WIN1252';
$$

AFTER LOAD DO $$
  SET session_replication_role = DEFAULT;
$$;

最后总结

核心是确保SQL Server数据编码 → pgLoader读取编码 → PostgreSQL会话编码这一整条链条完全对齐。先通过小批量测试定位具体错误行,确认编码匹配后再放大批量参数。如果测试后还是有问题,把错误日志里的具体行贴出来,就能精准定位是某个特殊字符的编码问题了。

火山引擎 最新活动