Oracle Skills 实战:AI 辅助 MySQL 迁移 Oracle
80 张表,5000 行建表语句,数百处致命问题------从数天人工审查压缩到 5 分钟自动化,这是用 Oracle Database Skills + AI Agent 完成 MySQL→Oracle 迁移的真实体验。本文重点演示如何让 AI 接入 Oracle Skills 来协助数据库工作。
一、迁移之痛:DDL 表结构转换是最大瓶颈
做过跨库迁移的人都清楚,数据搬运不是最难的------mysqldump 导出、SQL*Loader 导入,工具链相对成熟。真正折磨人的是 DDL 表结构的兼容性转换。
两个数据库虽然都叫"关系型数据库",但在类型体系、关键字规则、索引约束、存储过程语法上的差异,远比想象的复杂。一个典型的迁移项目中,DDL 转换通常要占总工时的 40% 以上。
看似简单的建表语句,埋了多少雷
拿一个中等规模的业务系统来说:80 张表、约 5000 行建表语句。如果用可视化建模工具从 MySQL 自动导出 Oracle 脚本,工具通常只能做最基础的字面转换------去掉反引号、把 AUTO_INCREMENT 替换为 IDENTITY------然后剩下大量的深层问题原封不动地留给你。
我最近在一个项目的 MySQL→Oracle 12c 迁移中,拿到这样一份"半成品" DDL 后,逐表检查了一遍,发现的问题比预想的多得多:
- 数据类型原样保留:BIGINT、TINYINT、SMALLINT、BIT------这四个关键字 Oracle 12c 一个都不认识。工具只转了 INT→NUMBER 和 VARCHAR→VARCHAR2,其他类型照搬了 MySQL 写法。
- UNSIGNED 修饰符遍布全文件 :Oracle 从来没有 UNSIGNED 这个概念。MySQL 允许
INT UNSIGNED,Oracle 会直接报语法错误。而这个文件中 UNSIGNED 出现了近 150 次。 - 列名与 Oracle 保留字冲突 :
SIZE、LEVEL、NUMBER------这些在 MySQL 中是合法的列名,到了 Oracle 就成了保留字,建表直接失败。 - 索引名跨表重复 :MySQL 允许不同表使用相同的索引名(如多个表都有
idx_flag)。Oracle 要求索引名在全 Schema 范围内唯一------20 多个索引名存在重复,必须逐个加表名前缀区分。 - JSON 类型不支持 :MySQL 5.7 起就支持原生 JSON 列,但 Oracle 直到 21c 才引入 JSON 类型。12c 环境下必须改为
CLOB并加IS JSON约束。
这些问题的任何一个,都会导致 CREATE TABLE 直接报错。按传统方式逐表审查、逐列对照、手动修改,两到三天的工作量起步。
二、Oracle Database Skills:把官方文档"注入" AI Agent
解决问题的关键是 Oracle Database Skills------Oracle 官方在 GitHub 上维护的一套 AI 技能仓库。
它是什么
简单说,这是一套结构化的技术指导文件,专门为 AI 编程助手(Claude Code、Codex、Hermes Agent 等)设计。仓库地址:https://github.com/oracle/skills 。
它并非传统的"把整本手册塞给 AI",而是采用了一种更聪明的设计:
oracle/skills/
├── db/ ← Oracle 数据库(本文核心)
│ ├── SKILL.md ← 路由索引(仅 5KB)
│ ├── migrations/ ← 迁移专题
│ │ ├── migrate-mysql-to-oracle.md
│ │ ├── migrate-postgresql-to-oracle.md
│ │ ├── migration-assessment.md
│ │ └── ...
│ ├── performance/ ← AWR/ASH/执行计划
│ ├── plsql/ ← 包设计/游标/异常
│ ├── security/ ← 权限/VPD/数据加密
│ ├── sql-dev/ ← SQL 调优/动态 SQL
│ └── ...共 18 个分类
├── oci/ ← Oracle Cloud
├── graal/ ← GraalVM
└── apex/ ← Oracle APEX
路由索引设计:按需加载,不浪费 Token
db/SKILL.md 只有 5KB,本身不包含具体知识。它是一张路由表:
| 你问什么 | AI 去读哪个文件 |
|---|---|
| MySQL 类型怎么映射到 Oracle? | migrations/migrate-mysql-to-oracle.md |
| 执行计划怎么分析? | performance/explain-plan.md |
| PL/SQL 包怎么设计? | plsql/plsql-package-design.md |
| Data Guard 怎么配置? | admin/data-guard.md |
AI Agent 只在回答问题时才去拉取对应的子文件。不相关的 17 个分类完全不进上下文,Token 消耗比全量注入降低了 90% 以上。
覆盖到什么程度
以迁移场景最常用的 migrate-mysql-to-oracle.md 为例,它覆盖了:
- 25 种以上数据类型的完整映射(含精度对应、示例 SQL)
- 24 个字符串函数转换(CONCAT→||、GROUP_CONCAT→LISTAGG 等)
- 16 个日期函数转换(含 MySQL↔Oracle 格式掩码对照表)
- 存储过程全量转换:变量声明、控制流(注意 ELSIF 不是 ELSEIF)、游标处理、异常捕获
- 数据迁移工作流:mysqldump 导出→Schema 转换→SQL*Loader 导入
所有转换建议都直接引用 Oracle 官方文档,每个示例都有完整的"改前 / 改后"代码对比,不是社区论坛水平的一句"试试 NUMBER 代替 INT"。
三、实战:如何让 AI Agent 接入 Oracle Skills 完成迁移
下面以 MySQL→Oracle 12c 迁移为例,演示从接入到完成的完整流程。
Step 1:接入 Oracle Skills
在 Hermes Agent 中安装 Oracle Skills 的 db 域:
bash
hermes skills install skills-sh/oracle/skills/db
安装后,164 个数据库相关的结构化文件自动可用。你也可以把常用的迁移参考文件下载到本地:
bash
mkdir -p ~/.hermes/skills/database/oracle-migration-review/references/
curl -o ~/.hermes/skills/database/oracle-migration-review/references/migrate-mysql-to-oracle.md \
https://raw.githubusercontent.com/oracle/skills/main/db/migrations/migrate-mysql-to-oracle.md
参考文件来源于 https://github.com/oracle/skills ,可按需下载任意子目录文件。
对于 Claude Code 或其他通用 AI 工具,可将
db/SKILL.md的路由表粘贴到项目的AGENTS.md中,AI 会自动按需拉取子文件。
Step 2:AI Agent 自动路由
把 DDL 文件交给 AI Agent(我用的是 Hermes Agent,也可以用 Claude Code 或 Codex):
用户: "帮我审查这份 MySQL DDL 在 Oracle 12c 上的兼容性"
↓
AI 判断: 这是迁移任务 → 触发 db skill
↓
查看路由表: migrations → migrate-mysql-to-oracle.md
↓
加载官方类型映射表作为权威参考
整个过程不需要手动指定用哪个 skill、读哪个文件------AI 自己判断。
官方 Skill 的盲区:知识完整,但缺执行
migrate-mysql-to-oracle.md 在类型映射上非常权威,但实际迁移中你会发现它有明显的覆盖盲区:
- 不含 Oracle 保留字列表------它只说了句"避免使用保留字做标识符",既没有列出哪些是保留字,也没有检测逻辑
- 不含索引名唯一性检查------MySQL 允许不同表同名索引,Oracle 要求全局唯一,这个差异它没提
- 不含 COMMENT ON 同步逻辑------改列名时注释也得跟着改,这个细节不在它的范围内
- FLOAT 语法差异标注不够 ------官方文档只说了 MySQL FLOAT 应对标 Oracle
BINARY_FLOAT,但没有区分FLOAT(p)单参数(显示宽度)和FLOAT(p,s)双参数(精度约束)两种语法。前者用BINARY_FLOAT完全对标;后者 Oracle 根本不支持BINARY_FLOAT(p,s)语法,必须改为NUMBER(p,s) - TEXT 族类型覆盖不全 ------TINYTEXT、MEDIUMTEXT、LONGTEXT 这些 MySQL 特有的文本类型并未在映射表中逐项列出,实际迁移中它们都需统一变为
CLOB - 不含自动检测和修正脚本------它是参考文档,不是执行工具
换句话说:官方 Skill 是字典,但你还需要一个编译器。
所以我在项目里写了一个配套的 Python 扫描脚本(约 150 行),把官方文档的映射规则变成可执行的检测和替换逻辑。下面按这个"字典 + 编译器"的组合来演示完整流程。
Step 3:扫描脚本自动化,3 秒出结果
脚本读取 DDL 后,按官方类型映射表逐一检查,一键输出:
text
🔴 致命问题(会导致 CREATE TABLE 失败)
├── BIGINT: 300+ 处 → 改为 NUMBER(19)
├── TINYINT: 50+ 处 → 改为 NUMBER(3)
├── SMALLINT: 8 处 → 改为 NUMBER(5)
├── BIT: 5 处 → 改为 NUMBER(n)
├── FLOAT(p,s): 3 处 → 改为 NUMBER(p,s)(双参数语法的精度约束)
├── FLOAT(p): 2 处 → 改为 BINARY_FLOAT(单参数显示宽度,对标 IEEE 754)
├── UNSIGNED: 150 处 → 删除该关键字
├── JSON: 2 处 → CLOB + IS JSON 约束
├── TINYTEXT: 3 处 → 改为 CLOB
├── MEDIUMTEXT: 4 处 → 改为 CLOB
└── 重复索引: 20+ 个 → 加表名前缀区分
🟡 保留字列名
├── SIZE → XXX_SIZE (3 处,含 COMMENT ON 同步)
├── LEVEL → AAA_LEVEL / BBB_LEVEL (3 处)
└── NUMBER → XXX_NUM (2 处)
🟠 设计建议
├── INT 类型 150+ 处 → Oracle 中 INT=NUMBER(38),建议改为 NUMBER(10)
└── 3 张表无主键 → 需业务确认
Step 4:官方文档兜底,边缘类型不抓瞎
扫描脚本处理常见类型足够快,但遇到 ENUM、BIT、GEOMETRY、MEDIUMINT 这种"一年碰不到几次"的类型时,直接查阅官方文件:
sql
-- MySQL ENUM 类型
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
status ENUM('pending','processing','shipped','delivered')
);
-- Oracle 等价写法(来自 migrate-mysql-to-oracle.md)
CREATE TABLE orders (
order_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
status VARCHAR2(20) NOT NULL,
CONSTRAINT chk_orders_status
CHECK (status IN ('pending','processing','shipped','delivered'))
);
不需要凭记忆猜,不需要翻 StackOverflow------官方文件给出了完整的类型对照表和可执行的示例代码。
Step 5:自动修正 + 验证
所有修改一次性完成,输出可直接在 Oracle 执行的文件。验证环节自动化:
text
残留检查结果:
BIGINT: 0 ✅
TINYINT: 0 ✅
SMALLINT: 0 ✅
UNSIGNED: 0 ✅
TINYTEXT: 0 ✅
MEDIUMTEXT: 0 ✅
保留字列名: 0 ✅
重复索引: 0 ✅
COMMENT ON 同步: 全部完成 ✅
FLOAT 语法检查: BINARY_FLOAT/NUMBER(p,s) 正确 ✅
四、避坑指南:三个容易犯的错误
坑 1:保留字检测的盲区
前面提到的扫描脚本,第一版的保留字检测正则只匹配了 6 种常见 Oracle 数据类型:
python
# ❌ 问题版本:类型列表太窄
col_defs = re.findall(r'^\s+(\w+)\s+(NUMBER|VARCHAR2|DATE|DECIMAL|CHAR|CLOB)', ...)
问题在于------这份 DDL 还没完成转换,大量列用的是 MySQL 类型(SIZE INT、LEVEL TINYINT)。这些列因为类型不在正则里,被直接跳过了保留字检测。
修法:把 MySQL 常见的列类型也加进去:
python
# ✅ 修复版本:覆盖 17 种常见类型
col_defs = re.findall(r'^\s+(\w+)\s+(NUMBER|VARCHAR2|DATE|DECIMAL|CHAR|CLOB|INT|BIGINT|TINYINT|SMALLINT|BIT|BLOB|RAW|TIMESTAMP|FLOAT|DOUBLE|VARCHAR)', ...)
坑 2:改列名忘了 COMMENT ON
Oracle 的 COMMENT ON COLUMN 语法里列名是硬编码字符串。把 SIZE 改成 XXX_SIZE 后,如果不更新 COMMENT ON:
sql
-- 改前列定义
SIZE INT,
-- 改后列定义
XXX_SIZE NUMBER(10),
-- 忘了改这个 👇
COMMENT ON COLUMN orders.SIZE IS '文件大小'; -- 指向不存在的列!
脚本必须同时替换列定义行和 COMMENT ON 行,用正则一次性完成。
坑 3:自动修正后必须验证,不要盲目信任
脚本可以帮你改 600 多处,但不代表改完就能直接上生产。有三件事必须手动确认:
- 改列名后检查关联代码 ------
SIZE改成XXX_SIZE,应用层的 SQL、ORM 映射、报表查询都得跟着改。脚本只管 DDL,管不了你的 Java 代码。 - 验证修正后的 DDL 能在目标 Oracle 版本上执行 ------12.1 和 12.2 的标识符长度限制不同(30 vs 128 字节),
IDENTITY列在 12.1 之后才支持。如果你的目标环境版本不确定,先确认。 - 残留检查不要只信脚本的报告 ------用
grep再扫一遍 BIGINT、TINYINT、UNSIGNED 等关键字,确保 0 残留。两次验证总比一次可靠。
记住:脚本是提效工具,最终拍板的是你。
坑 4:FLOAT 参数语法,单双有别
MySQL 的 FLOAT 在 Oracle 中有个大坑------参数数量的含义完全不同:
sql
-- MySQL -- Oracle 映射
OPACITY FLOAT(12) -- BINARY_FLOAT(p=显示宽度,不约束值)
CT_SCORE FLOAT(2,1) -- NUMBER(2,1)(p,s=精度+标度,真约束)
RATIO FLOAT(5,3) -- NUMBER(5,3)
关键规则:
| 语法 | 含义 | Oracle 映射 | 原因 |
|---|---|---|---|
FLOAT(p) 单参数 |
显示宽度 | BINARY_FLOAT |
IEEE 754 单精度完全对标 |
FLOAT(p,s) 双参数 |
精度+标度 | NUMBER(p,s) |
Oracle 无 BINARY_FLOAT(p,s) 语法 |
两个常见错误:
- 用
NUMBER(12)映射FLOAT(12)→ Oracle 中NUMBER(12)是整数,会截断所有小数位 - 用
NUMBER(18,6)试图"万能兜底" → FLOAT 的范围是 ±3.4×10³⁸,NUMBER(18,6)上限只有约 10¹²,超出直接报错
五、延伸:不止迁移,18 个分类覆盖全链路
db 域下除了 migrations/,还有另外 17 个分类值得 DBA 关注:
| 分类 | 解决什么问题 |
|---|---|
performance/ |
慢 SQL 诊断:explain plan→wait events→optimizer stats→AWR reports |
plsql/ |
包设计规范、游标优化、异常处理最佳实践 |
security/ |
最小权限原则、VPD 行级安全、TDE 透明加密 |
sql-dev/ |
SQL 调优 Checklist、动态 SQL 安全写法、SQL 注入防护 |
sqlcl/ |
SQLcl Liquibase 做版本化迁移、MCP Server 让 AI 直连数据库 |
admin/ |
Data Guard 搭建、redo/undo 管理、用户与角色 |
devops/ |
Schema 在线变更、Edition-Based Redefinition、零停机迁移 |
这些分类都是"用到时才加载"的模式。装一个 db 入口就够,不需要担心 Token 膨胀。
六、效率实测
| 维度 | 纯人工审查 | Oracle Skill + AI Agent |
|---|---|---|
| 审查耗时 | 2~3 天(逐表逐列核对) | ~5 分钟(自动扫描 + 人工复核) |
| 漏检风险 | 数百处问题,人工极易遗漏 | 脚本 + 官方类型表双重验证 |
| COMMENT ON 同步 | 手工逐行修改,容易漏 | 脚本自动同步 |
| 可复现性 | 依赖审查人经验 | 脚本可重复执行 |
| 版本差异处理 | 凭个人记忆(12.1 vs 12.2 标识符长度等) | 官方文档明确标注版本差异 |
| 边缘类型处理 | 需要查官方文档或社区 | 官方文件直接给出对照表和示例 |
七、总结与建议
Oracle Database Skills 把 Oracle 官方技术文档结构化地注入了 AI Agent,让数据库迁移从「人肉逐行审查」变成了「Agent 自动扫描 + 官方文档验证」。
接入 Oracle Skills 的操作步骤:
- 安装 db 域 :
hermes skills install skills-sh/oracle/skills/db - 本地缓存 :把
migrate-mysql-to-oracle.md等常用文件下载到~/.hermes/skills/目录,避免 GitHub 不可达时影响工作 - 编写自建脚本 :官方 Skill 保证类型映射的准确性,自建脚本保证检测和修正的效率------两者加起来才是完整的 Oracle AI 工作流
把重复性的兼容性检查交给 Agent,把精力留给真正需要专业判断的------比如分区策略选择、索引设计优化、迁移切换方案制定。
📎 相关链接
- Oracle Skills 仓库:https://github.com/oracle/skills
- Hermes Agent:https://github.com/NousResearch/hermes-agent