Navicat 17不能一键成功迁移MySQL到Oracle,因其数据传输功能仅执行批量INSERT且不自动生成建表语句、序列、触发器,也不处理AUTO_INCREMENT语义映射;必须手动配置转换对象名为大写、遇到错误继续、禁用外键限制,并补全自增主键、字符集及日期类型适配。
navicat 17 能直接迁移 mysql 到 oracle,但必须手动处理自增主键、大小写、字段类型映射和外键约束——跳过这些步骤,90% 的迁移会卡在 ora-00942: table or view does not exist 或插入失败。
为什么 Navicat 17 的“数据传输”不能一键成功
Navicat 17 的 数据传输 功能底层仍是批量生成 INSERT 语句 + 执行,它不自动建表、不自动创建序列、也不识别 MySQL 的 AUTO_INCREMENT 语义。Oracle 没有原生自增字段(12c+ 的 GENERATED BY DEFAULT AS IDENTITY 是语法糖,需显式声明),而 Navicat 默认不会为你改 DDL。常见失败点包括:
- MySQL 表名
user_info迁过去变成小写,在 Oracle 中查不到,报ORA-00942; -
INT字段被转成NUMBER(10,0),但某些 ORM 会因精度声明不匹配拒绝映射; - 含外键的表因目标表无约束或顺序错乱,INSERT 报
ORA-02291; - 时间字段从 MySQL 的
DATETIME映射为 Oracle 的DATE,但时区/毫秒精度丢失,查询范围失效。
必须勾选的三个高级选项
打开 工具 → 数据传输 后,在“高级”选项卡中这三项不是可选,是必选:
-
转换对象名为大写:强制把所有表名、字段名转成大写,避免双引号包裹和大小写敏感问题; -
遇到错误继续:否则一条记录失败就中断整个表; -
禁用外键限制(即取消勾选“外键限制”):否则带外键的表无法单独插入,会因父表未就位报错。
注意:转换对象名为大写 也会自动给 Oracle 关键字加双引号(如 "USER"),这是保护机制,别关它。
自增主键必须手工补全
Navicat 不会为你创建序列或触发器,也不会改表结构加 IDENTITY。迁移后立刻执行以下任一方案:
- Oracle 12c+:用
ALTER TABLE t ADD id NUMBER GENERATED BY DEFAULT AS IDENTITY;(注意:必须先删掉原ID字段再加,不能直接修改); - 通用方案:建序列 + 触发器,例如:
CREATE SEQUENCE t_id_seq START WITH 1 INCREMENT BY 1; CREATE OR REPLACE TRIGGER t_id_trg BEFORE INSERT ON t FOR EACH ROW WHEN (new.id IS NULL) BEGIN :new.id := t_id_seq.NEXTVAL; END;
- 如果已有数据,还需同步序列起始值:
SELECT MAX(id) FROM t,然后ALTER SEQUENCE t_id_seq RESTART START WITH <max+1>。
容易被忽略的字符集与日期细节
Navicat 17 默认用客户端字符集读取 MySQL 数据,若 MySQL 是 utf8mb4 而 Oracle 是 AL32UTF8,通常没问题;但一旦源库含 emoji 或四字节字符,仍可能截断。更隐蔽的问题在日期:
- MySQL 的
DATETIME('2026-07-28 15:30:45.123')会被存进 OracleDATE字段,但DATE不存毫秒——.123直接丢弃; - 后续用
TO_DATE()查询时,必须用yyyy-mm-dd hh24:mi:ss格式,不能带毫秒,否则报ORA-01830; - 稳妥做法:迁移前在 MySQL 中把时间字段转成字符串导出,或在 Oracle 中统一用
TIMESTAMP类型替代DATE。
真正卡住人的从来不是按钮点几下,而是迁移后第一笔 INSERT 报错时,你得知道该去查序列、查大小写、还是查字段精度。


















