MySQL迁移需分三步:先转结构、再调语义、最后迁数据;自动工具漏主键和NOT NULL因不识别Oracle隐式约束,如ROWID逻辑主键或物化视图定义的非空性。

不能直接“导入”,必须分三步走:先转结构、再调语义、最后迁数据——跳过任何一步,上线后必出错。
为什么 MySQL Workbench 的自动映射会漏掉主键和 NOT NULL?
AWS SCT 和 MySQL Workbench 都按 Oracle 的元数据做保守推断,但它们不识别隐式约束。比如 Oracle 表用 ROWID 当逻辑主键、或通过物化视图定义 NOT NULL,工具根本不会生成对应 DDL。
- 导出前在 Oracle 中执行:
SELECT table_name, column_name FROM all_tab_columns WHERE nullable = 'N' AND data_type IN ('VARCHAR2','CHAR','NUMBER'),人工核对生成的 MySQL DDL - 把自动生成的
TEXT字段全部改成VARCHAR(16383)(MySQL 8.0.30+ 支持),并补上NOT NULL DEFAULT '' - 用
mysqlsh --sql -e "ALTER TABLE t ADD PRIMARY KEY (id)"批量补主键,别依赖 GUI 向导的“自动推荐”
Oracle 的 SEQUENCE、ROWNUM、CONNECT BY 怎么在 MySQL 8.0 里落地?
MySQL 8.0 没有等价语法,强行映射只会让 SQL 报错或语义错乱。比如 ROWNUM <= 10 直接转成 LIMIT 10 看似可行,但 Oracle 的 ROWNUM 是在 WHERE 之后、ORDER BY 之前计算的,而 LIMIT 是最后截断——结果可能完全不同。
-
SEQUENCE.NEXTVAL→ 改用AUTO_INCREMENT+ 应用层预取,或改写为INSERT ... ON DUPLICATE KEY UPDATE避免并发冲突 -
ROWNUM分页 → 必须重写为带游标偏移的ORDER BY id LIMIT 10 OFFSET 20,且id必须是索引列 -
CONNECT BY层级查询 → 改用 MySQL 8.0 的WITH RECURSIVE,但注意递归深度默认限 1000 层,需调大cte_max_recursion_depth
PL/SQL 存储过程能靠 AWS SCT 自动转吗?
不能。SCT 自带的 oracle_to_mysql 扩展只处理基础函数,比如 NVL→IFNULL、TO_CHAR→DATE_FORMAT;但一遇到 FOR rec IN (SELECT ...)、EXCEPTION WHEN NO_DATA_FOUND 或 PRAGMA AUTONOMOUS_TRANSACTION,生成的代码就只是语法通、逻辑死。
- 显式游标必须拆成
DECLARE cur CURSOR FOR ...; OPEN cur; FETCH cur INTO ...;,且每个FETCH后要手动判NOT FOUND -
EXCEPTION块 → 全部换成DECLARE CONTINUE HANDLER FOR NOT FOUND,且 handler 只在当前BEGIN...END块内有效 -
PRAGMA AUTONOMOUS_TRANSACTION→ MySQL 完全不支持,必须提到应用层,用两阶段提交或补偿事务实现
最易被忽略的一点:Oracle 的 DATE 类型实际包含时分秒,而 MySQL 的 DATE 不含时间部分。迁移时若没统一映射为 DATETIME,大量时间字段会变成 0000-00-00 或被截断——这种错误上线后很难回溯,因为数据已丢失。


















