navicat 无真正智能映射,其“自动识别类型”默认开启但不可靠,必须手动关闭并逐字段映射;关键需将 tinyint(1) 显式映为 boolean/bit、datetime 映为 timestamp with time zone、json 映为 jsonb、text 手动映射为 text,并校验驱动上报类型与实际 ddl 一致性。

Navicat 没有“智能映射”——所谓智能,其实是默认硬编码规则 + 静默 fallback,不手动干预 90% 会出错。
为什么“自动识别类型”必须关掉
Navicat 在数据传输向导里默认勾选 Auto-detect data types,它会根据源字段名(如 is_active)、长度(TINYINT(1))和数据库方言猜目标类型。但这个“猜”不可控:MySQL 的 TINYINT(1) 可能被塞进 PostgreSQL 的 SMALLINT 而不是 BOOLEAN;DATETIME 可能变成 TIMESTAMP WITHOUT TIME ZONE,导致时区偏移。
- 在数据传输向导中,点右下角
高级→ 切到字段映射标签页 → 取消勾选Auto-detect data types - 关闭后,所有列都会显示为“未映射”,强制你逐个确认,避免隐式错误
- 该设置只对当前任务生效,每次新建传输都得重设
手动映射关键字段类型的实操清单
以下映射不是可选项,而是跨 MySQL→PostgreSQL 或 MySQL→SQL Server 时的必调项。Navicat 内置规则不覆盖这些异构路径,不改就等着数据错位或插入失败。
-
TINYINT(1)→ 显式选BOOLEAN(PostgreSQL)或BIT(SQL Server),并在“转换表达式”填CASE WHEN ? = 1 THEN 1 ELSE 0 END -
DATETIME/TIMESTAMP→ PostgreSQL 目标必须选TIMESTAMP WITH TIME ZONE,不能用 WITHOUT;SQL Server 源需先用CONVERT(VARCHAR, col, 126)转字符串再传 -
JSON→ PostgreSQL 必须映射为jsonb;若已误传成text,后续得手动执行ALTER TABLE t ALTER COLUMN j TYPE jsonb USING j::jsonb -
TEXT→ 不要依赖下拉推荐值(常 fallback 成VARCHAR(255)),点Add手动加规则:source type: TEXT→target type: TEXT
映射生效但 DDL 还是错?检查驱动和大小写
你明明在字段映射页把 DATETIME 设成了 TIMESTAMP WITH TIME ZONE,生成的目标建表语句里却还是 TIMESTAMP——这不是配置没保存,而是底层 PostgreSQL JDBC 驱动把 TIMESTAMP WITH TIME ZONE 元数据上报为 TIMESTAMP,Navicat 捕获不到完整类型信息。
- 验证方式:在 PostgreSQL 中执行
\d table_name,看实际列类型是否带WITH TIME ZONE - 若发现不一致,绕过 Navicat DDL 生成,改用
pg_dump --schema-only导出基线结构,再人工补上WITH TIME ZONE修饰符 - 字段名注意全小写:PostgreSQL 默认大小写敏感,
CreatedAt和createdat是两个字段,Navicat 同步后查询报column does not exist很可能就是这个原因
同步前必须做的三件事,缺一不可
类型映射只是起点,真正决定成败的是迁移前的结构校验和连接参数控制。很多“卡在 95%”或“中文变问号”的问题,根源不在映射本身。
- 在 MySQL 连接属性的
高级页,手动追加启动命令:SET client_encoding='UTF8'(仅靠连接串里的client_encoding=UTF8不可靠) - 目标 PostgreSQL 表若已有数据,提前运行
SELECT setval('table_id_seq', (SELECT MAX(id) FROM table)),否则不勾选Reset sequences就会主键冲突 - 禁用
Commit every X rows,改用Commit entire table:跨库网络延迟高,分段提交反而增加事务开销和失败概率
类型映射不是点几下就能跑通的配置项,它是连接、驱动、元数据、目标库约束四层耦合的结果。最易被忽略的是驱动上报的类型精度丢失——你看到的映射界面,未必等于最终执行的 DDL 或 INSERT 语义。











