Navicat Premium无法一键完成Oracle到PostgreSQL迁移,必须分步干预:先仅创建表结构并手动修正数据类型(如NUMBER→numeric无精度、DATE→timestamp、CLOB→text)、字段名小写化、补全序列;再配置数据传输参数(禁用完整插入语句、目标表名小写、启用BLOB十六进制);最后验证总数、抽样数据和业务SQL逻辑。
navicat premium 能把 oracle 数据导入 postgresql,但不能一键完成——它只负责搬运结构和数据,不自动修复语法、类型或逻辑兼容性问题。实际迁移中,90% 的失败都卡在表结构创建后、数据写入前的类型映射环节。
为什么直接“数据传输”会失败
Oracle 和 PostgreSQL 对同一语义的数据类型处理差异极大:NUMBER(10,2) 在 Oracle 中是固定精度小数,但 Navicat 默认转成 numeric(10,2),而目标表若已有该字段且长度不足(比如原表有 NUMBER(15,4)),插入时就会报错 ERROR: numeric field overflow;VARCHAR2(200) 会被转为 character varying(200),看似没问题,但 Oracle 允许尾部空格比较相等,PostgreSQL 不默认这样行为,业务 SQL 可能悄然出错。
必须手动干预的表结构环节
- 先用
Navicat的“数据传输”功能仅勾选 创建表,不要勾选“插入记录” - 传输完成后,立刻进
pgAdmin 4或Navicat的表设计界面,逐个检查字段类型: -
NUMBER→ 改为numeric(无精度限制),不是numeric(p,s) -
DATE→ PostgreSQL 没有时间部分,要改用timestamp without time zone才能保留时分秒 -
CLOB→ 必须改为text,不能留character large object(PostgreSQL 不识别该类型) - 含双引号的字段名(如
"User_ID")→ 立刻重命名为小写无引号形式(user_id),否则后续所有INSERT都会因找不到列名失败 - 确认主键、序列、索引是否已重建——
Navicat不自动创建序列,serial类型需手动补上nextval()默认值
数据导入时的关键参数设置
第二次运行 Navicat 的“数据传输”,这次只勾选 插入记录,并注意:
- 务必取消勾选
使用完整插入语句—— Oracle 的TO_DATE('2023-01-01','YYYY-MM-DD')会被原样写入 SQL 文件,PostgreSQL 不认这种写法,关掉后Navicat会转成标准 ISO 格式字符串 - 传输模式选
高级,目标表名填小写(如orders),即使源表是ORDERS,否则找不到目标表 - 勾选
遇到错误继续是危险操作:它会让一条失败的INSERT跳过,但你根本看不到哪条数据丢了,建议先关掉,等首次运行报错后针对性修复 - 大文本或二进制字段(
BLOB/CLOB)务必勾选为BLOB使用十六进制格式,否则乱码或截断
迁移后必须验证的三个点
数据“进去”不等于“可用”。导完立刻查:
- 执行
SELECT COUNT(*) FROM orders;和 Oracle 端比对总数——Navicat默认跳过空行或 NULL 值,可能少几条 - 抽样查一条含小数、日期、中文的记录,用
SELECT * FROM orders WHERE id = 12345;看值是否完整、无截断、无乱码 - 跑一条典型业务 SQL,比如
WHERE created_date >= '2023-01-01',确认日期字段能正常参与比较——很多问题出在时区或类型隐式转换上
最常被忽略的是 Oracle 的 NVL()、DECODE()、ROWNUM 这类函数,在 PostgreSQL 里得全换成 COALESCE()、CASE WHEN、ROW_NUMBER(),这些不在 Navicat 处理范围内,得靠代码层逐个替换。


















