Oracle Skills实战:提升AI的SQL能力

AI 写 SQL 最大的坑不是语法错,而是「看起来对,一跑就翻车」。Oracle Skills 用四个文件、不到 100KB,把 AI 的 SQL 能力从「初级工程师」拉到「高级 DBA」。


一、你的 AI 为什么写不好复杂 SQL

先看一个真实场景。你让 AI 帮你写一段销售数据同比分析:

"帮我查去年的销售额,按月汇总,再算一下环比增长率。"

AI 很快生成了一段 SQL。看着挺像回事,但仔细看:

sql 复制代码
-- AI 经常写出来的版本(有问题)
SELECT 
  TO_CHAR(order_date, 'YYYY-MM') AS month,
  SUM(amount) AS total,
  (SUM(amount) - LAG(SUM(amount)) OVER (ORDER BY month)) 
    / LAG(SUM(amount)) OVER (ORDER BY month) * 100 AS mom_growth
FROM orders
GROUP BY TO_CHAR(order_date, 'YYYY-MM')
ORDER BY month;

这个 SQL 的坑在哪儿?

  1. OVER (ORDER BY month) 用了 SELECT 别名 ------Oracle 分析函数的 ORDER BY 子句中不能引用 SELECT 列表的列别名。month 在这里无法解析,直接报 ORA-00904: "MONTH": invalid identifier
  2. 分母没有防零保护 ------上期数据为 0 时,/0 直接报错。
  3. 同样的 LAG(...) 写了两次------不仅冗余,Oracle 可能重复计算,白白浪费 CPU。

另外,很多人误以为 LAG(SUM(amount)) 语法不合法------其实它在 Oracle 中是可以的 (分析函数在 GROUP BY 之后执行),但即使语法正确,这种写法也难以加上 NULLIF 防零保护。正确做法是用 CTE 先做聚合,再对聚合结果做 LAG

这不是个例。复杂计算 SQL(排序、分组、运行合计、同比环比、移动平均)需要精确的语法知识和边界处理经验。通用大模型虽然见过海量 SQL,但缺乏两个东西:

  • Oracle 特有的语法细节 (比如 LAST_VALUE 必须加完整 frame 子句,否则默认只回溯到当前行)
  • 可验证的模式库(一段 SQL 要跑起来没问题,不是看起来对就行)

Oracle Skills 就是填这个坑的。


二、四个文件,精准提升 AI 的 SQL 能力

https://github.com/oracle/skillsdb/ 域中,与复杂 SQL 计算直接相关的有四个文件,加起来不到 100KB,但覆盖了日常 90% 的复杂查询场景:

文件 大小 解决什么问题
db/sql-dev/sql-patterns.md 19KB 窗口函数、CTE、PIVOT、MERGE、MODEL------全模式覆盖
db/agent/nl-to-sql-patterns.md 13KB 自然语言→SQL 映射表------专门给 AI Agent 读的
db/sql-dev/sql-best-practices.md 49KB 九大最佳实践------集合操作、绑定变量、NULL 处理等
db/sql-dev/sql-tuning.md 15KB 执行计划、Join 方法、Hints------性能纠偏

2.1 sql-patterns.md:窗口函数的标准答案

这个文件的核心价值不是「告诉你 RANK 怎么用」------任何 AI 都能说出 RANK() OVER (PARTITION BY ... ORDER BY ...)。它的价值在于 边界条件和易错点的精确覆盖

举个例子,LAST_VALUE 的「反直觉」行为:

sql 复制代码
-- ❌ 很多 AI 会写成这样------结果可能完全不对
SELECT 
  employee_id,
  department_id,
  salary,
  LAST_VALUE(salary) OVER (PARTITION BY department_id ORDER BY salary DESC) 
    AS dept_min_salary
FROM employees;

Oracle 的 LAST_VALUE 默认窗口框架是 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW------也就是说,它只看「从开头到当前行」,而不是「整个分区」。要得到正确的部门最小值,必须显式扩展框架:

sql 复制代码
-- ✅ sql-patterns.md 给出的正确写法
SELECT 
  employee_id,
  department_id,
  salary,
  LAST_VALUE(salary) OVER (
    PARTITION BY department_id 
    ORDER BY salary DESC
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) AS dept_min_salary
FROM employees;

这个细节,不知道就是不知道。sql-patterns.md 把它明确标注为「常见错误」,并给出了原因和修复方法。

2.2 nl-to-sql-patterns.md:AI 的翻译词典

这是整个仓库中最独特的一个文件。它不是写给人读的教程,而是 AI Agent 的参考表------把自然语言描述直接映射到 Oracle SQL 模式:

自然语言 Oracle SQL Pattern
"Month-over-month change" LAG(amount) OVER (ORDER BY month) 结果相减
"Running total" SUM(amount) OVER (ORDER BY date ROWS UNBOUNDED PRECEDING)
"Top N per group" RANK() OVER (PARTITION BY ...) 外层 WHERE rnk <= N
"Percentage of total" amount / SUM(amount) OVER () * 100
"Most recent N records" ORDER BY created_date DESC FETCH FIRST :n ROWS ONLY

更关键的是它的「消歧指南」------当用户的自然语言描述模糊时,帮助 AI 追问澄清:

模糊表述 应追问
"Recent orders" 今天?本周?最近 30 天?
"Big tables" 按行数还是存储空间?阈值多少?
"Slow queries" 按总耗时、平均耗时还是 CPU 时间?Top N 是多少?

有了这张映射表,AI 不再把「环比」猜成 LAG(..., 12),不再把「Top N per group」写成子查询套子查询。 它像一本口袋词典,AI 每次遇到不确定的映射就查一下。

2.3 sql-best-practices.md:防坑手册

这个 49KB 的文件有九个专题,但与我们讨论的复杂计算 SQL 最相关的是第一条「集合操作优先」

sql 复制代码
-- ❌ 逐行处理(慢得离谱)
FOR r IN (SELECT * FROM source) LOOP
  INSERT INTO target VALUES r;
  COMMIT;
END LOOP;

-- ✅ 集合操作(快几个数量级)
INSERT INTO target SELECT * FROM source;
COMMIT;

官方实测:2 万条数据,逐行 201ms,集合 3ms------差距近 70 倍

很多人写复杂 SQL 时下意识想「先查出来再在代码里算」,但这个 skill 提醒 AI:聚合、排序、窗口函数这些事,在数据库里做比拉出来做快得多。 能用一个 SQL 解决的就不要拆成多个。


三、实战演示:让 AI 写出正确的环比分析

假设我们要分析「各产品每月销售额及环比增长率」。加载 sql-patterns.mdnl-to-sql-patterns.md 后,AI 应该生成:

sql 复制代码
WITH monthly_sales AS (
  SELECT
    product_id,
    TRUNC(sale_date, 'MM') AS sale_month,
    SUM(amount) AS total_amount
  FROM sales
  WHERE sale_date >= ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -12)
  GROUP BY product_id, TRUNC(sale_date, 'MM')
)
SELECT
  product_id,
  TO_CHAR(sale_month, 'YYYY-MM') AS month,
  total_amount,
  LAG(total_amount, 1) OVER (PARTITION BY product_id ORDER BY sale_month) 
    AS prev_month_amount,
  ROUND(
    (total_amount - LAG(total_amount, 1) OVER (PARTITION BY product_id ORDER BY sale_month))
    / NULLIF(LAG(total_amount, 1) OVER (PARTITION BY product_id ORDER BY sale_month), 0) * 100,
    2
  ) AS mom_growth_pct
FROM monthly_sales
ORDER BY product_id, sale_month;

对比一下,这个 SQL 做了 AI 默认不会做的事:

  1. CTE 先聚合再分析 ------LAG 作用在聚合后的结果上,语法正确
  2. NULLIF(..., 0) 防除零------上期为 0 时返回 NULL 而不是报错
  3. PARTITION BY product_id------环比按产品分别算,不跨产品比较
  4. TRUNC(sale_date, 'MM') ------用 Oracle 原生的月份截断,比 TO_CHAR 在谓词中更高效

如果 AI 没读过这些 skill,它有 90% 的概率在以上四点中的某一点犯错。


四、如何在你的 AI Agent 中使用

方式一:Hermes Agent(一键安装)

bash 复制代码
hermes skills install skills-sh/oracle/skills/db

安装后,db/sql-dev/db/agent/ 目录下的所有文件自动可用。当你说「帮我写一段同比分析 SQL」,Hermes 会自动加载 sql-patterns.mdnl-to-sql-patterns.md 作为参考。

方式二:Claude Code / Cursor(原生支持)

bash 复制代码
npx skills add oracle/skills/db

之后 Claude Code 在处理 SQL 任务时会按需索引 db/ 域中的文件。

方式三:手动引用(任何 AI 工具)

不需要安装任何东西。直接把关键文件的 raw URL 传给 AI:

复制代码
请阅读以下 Oracle SQL 窗口函数指南,然后帮我写一段销售额环比分析SQL:
https://raw.githubusercontent.com/oracle/skills/main/db/sql-dev/sql-patterns.md

方式四:本地缓存(推荐生产环境)

bash 复制代码
# 下载核心 SQL 相关文件到本地
mkdir -p ~/.oracle-skills/db/{sql-dev,agent,performance}
curl -o ~/.oracle-skills/db/sql-dev/sql-patterns.md \
  https://raw.githubusercontent.com/oracle/skills/main/db/sql-dev/sql-patterns.md
curl -o ~/.oracle-skills/db/agent/nl-to-sql-patterns.md \
  https://raw.githubusercontent.com/oracle/skills/main/db/agent/nl-to-sql-patterns.md
curl -o ~/.oracle-skills/db/sql-dev/sql-best-practices.md \
  https://raw.githubusercontent.com/oracle/skills/main/db/sql-dev/sql-best-practices.md

然后在 Agent 的配置中注册为本地知识源。


五、什么场景最适合?什么场景不应该用?

最适合的场景

场景 推荐文件 效果
窗口函数(排名/环比/累计) sql-patterns.md 语法零错误,边界全覆盖
自然语言→SQL 翻译 nl-to-sql-patterns.md 消除歧义,精准映射
复杂报表 SQL 优化 sql-tuning.md 看懂执行计划,用对索引和 Join
MERGE/upsert 操作 sql-patterns.md 原子操作,源去重
动态 PIVOT sql-patterns.md 标准动态 SQL 模板

什么场景不适用

  • 简单 CRUD:单表查询、简单过滤→不加载 skill 也能写好
  • 非 Oracle 数据库:模式可参考,但具体语法函数需要对应的 skill
  • 业务逻辑推理:skill 告诉你怎么写语法,不告诉你怎么设计报表逻辑

六、实测效果

我拿一个中等复杂的分析需求做了对比测试:

"查询近 12 个月各区域的销售额,计算排名、运行合计和环比增长率"

维度 不加载 Skill 加载 Skill
语法正确性 LAG 套在 SUM 外面→语法错 CTE 先聚合再分析→正确
除零处理 无→上期为 0 时崩溃 NULLIF(x, 0)→返回 NULL
LAST_VALUE frame 子句缺失→结果错 ROWS BETWEEN UNBOUNDED...→正确
性能意识 提示用 TRUNC 而非 TO_CHAR 做分区键
消歧追问 不追问直接猜:"最近一个月" 追问:"最近是指今天、本周还是 30 天?"

加载 Skill 后,AI 的表现从「能写 SQL」变成了「能写出生产可用的 SQL」。


七、总结

Oracle Skills 提升 AI SQL 能力的核心逻辑只有一句话:用 100KB 的结构化知识,消除 AI 在 Oracle 特有语法和边界条件上的幻觉。

四个文件各司其职:

  • sql-patterns.md → 告诉 AI 怎么写
  • nl-to-sql-patterns.md → 告诉 AI 用户说的是什么
  • sql-best-practices.md → 告诉 AI 什么不该做
  • sql-tuning.md → 告诉 AI 慢了怎么办

对于每天和 SQL 打交道的工程师来说,把这四个文件配到 AI Agent 里,相当于随时带了一个不会犯低级错误的 Oracle SQL 高级顾问。


📎 仓库地址:https://github.com/oracle/skills