2026年初,我第一次把业务SQL交给AI来写。半年过去了,我的数据库没炸,但血压确实高了几次。
这篇文章不讲「AI写SQL的5个工具推荐」,只讲我在真实项目里踩过的坑、流过的汗、以及最终沉淀下来的方法论。如果你也在用AI和数据库打交道,希望这些教训能让你少走弯路。
第一阶段:「好爽」——前两周的蜜月期
接手的是一个电商BI项目,几十张表,业务逻辑复杂。以前写一个报表SQL至少要半天:先理解业务需求,再翻文档找表结构,然后写SQL、调优、测试。
有了AI之后,我把需求描述扔给Cursor或者ChatGPT,10秒就出一版SQL。粘贴到DBeaver里运行,大部分时候直接出结果。
第一个月,我写报表的效率提升了至少3倍。
当时的感受就是:这技术太牛了,以后再也不用手写SQL了。
第二阶段:「好慌」——数据对不上的那一天
蜜月期在第二个月被打破了。
那天业务方问了一个很简单的问题:「上个月的用户留存率是多少?」我用AI写了一个SQL,跑了数据,给了答案。
第二天,业务方拿着另一份数据来找我:「两个数据差了8个百分点。」
我开始排查。翻出AI生成的SQL,逐行看。看了半小时,发现了一个微妙的问题:
-- AI生成的代码
SELECT
COUNT(DISTINCT user_id) AS active_users,
COUNT(DISTINCT CASE WHEN login_date >= '2026-04-01' THEN user_id END) AS retained_users
FROM user_actions
WHERE action_date >= '2026-03-01'
看起来没问题对吧?但AI在FROM子句里只用了user_actions表,它没有考虑到「有些用户注册了但没有任何行为记录」的情况。那些注册后沉默的用户,在这个SQL里根本没有出现。
这个SQL漏掉了大约8%的流失用户。
那一刻我才意识到:AI写的SQL,语法是对的,逻辑是错的。 这种错,比语法错误可怕一万倍——因为SQL能跑通,结果看起来也合理,只有跟真实数据对比才能发现问题。
第三阶段:那些年AI让我翻过的车
半年下来,我遇到了至少几十次AI编出来的SQL翻车。我挑了记忆最深刻的12个:
翻车1:COUNT(DISTINCT) 导致的内存溢出
AI在写一个留存分析SQL时,对7000万行数据用了COUNT(DISTINCT user_id),然后JOIN了另外两个大表。查询跑了8分钟,直接把分析数据库的CPU打到100%。
不是不能用COUNT(DISTINCT),但AI从不考虑数据量级。对AI来说,100条和1000万条,写出来的SQL结构是一样的。
翻车2:隐式类型转换导致的精度丢失
有一个金额字段存储为VARCHAR,AI生成SQL时直接做了字符串拼接来求和。结果是「12.5」+「8.30」=「12.58.30」。
-- AI写的(错的)
SELECT SUM(amount) FROM orders
-- 实际上amount是VARCHAR,SUM隐式转换后拼接了字符串
正确做法是先CAST(amount AS DECIMAL(10,2))再求和。
翻车3:LEFT JOIN 时的 ON 条件过于宽松
AI在做订单和退款关联时写了:
LEFT JOIN refunds r ON o.order_id = r.order_id
但它没加r.status = 'completed'条件。结果一个退款中的订单也被算作已退款,退款金额统计多了30%。
翻车4:时间范围处理差异
AI对不同数据库的时间函数理解经常出问题。在MySQL里写DATE(created_at)没问题,到了ClickHouse还写同样的函数,结果报错。改成ClickHouse的toDate(created_at)后又忘了时区转换。
翻车5:窗口函数的分区边界搞错
写ROW_NUMBER()做去重时,AI经常少写PARTITION BY字段:
ROW_NUMBER() OVER (ORDER BY create_time DESC) AS rn
-- 应该是 PARTITION BY user_id ORDER BY create_time DESC
结果是全局排序而非按用户分组排序,数据瞬间全乱。
翻车6:NULL值处理不当
有个计算客单价的场景,AI写了total_amount / order_count。但当order_count为0时,SQL直接抛除零错误。用NULLIF(order_count, 0)这种写法,AI需要你明确提示才记得加上。
翻车7: JOIN 顺序不优化
AI在处理5表JOIN时,从来不考虑join顺序和过滤条件下推。生成出来的SQL,小表驱动大表还是大表驱动小表,完全随机。对于大数据量,这可能意味着几秒和几分钟的差别。
翻车8:GROUP BY 字段不完整
在处理聚合查询时,AI生成的SQL偶尔在SELECT列里加了不在GROUP BY中的非聚合字段。这在MySQL的严格模式下会报错,在宽松模式下则返回错误数据。
翻车9:子查询性能灾难
AI喜欢用嵌套子查询,一层套一层,像个俄罗斯套娃。我见过它生成了5层嵌套的SQL,EXPLAIN一看,全表扫描扫描了5次。
每次这种时候我都得手动把子查询改写成CTE或者临时表。
翻车10:分页查询的OFFSET陷阱
AI写分页查询,永远是LIMIT 10 OFFSET 20。对于几千条数据没问题,但到了百万级,OFFSET越大性能越差。它从来不会主动考虑游标分页或者keyset pagination。
翻车11:SELECT * 的幽灵
虽然这是个老生常谈的问题,但AI尤其爱写SELECT *。在宽表里,这可能导致不必要的网络传输和内存使用。更隐蔽的是,如果后来表结构变了,SELECT *的应用代码可能直接崩。
翻车12:Mixing不同数据库方言
这是最令我头疼的一类。我同时管理MySQL和ClickHouse两个数据源。AI经常把MySQL的IFNULL写在ClickHouse里(应该是ifNull),或者把ClickHouse的arrayJoin用在MySQL里。
如果不在prompt里明确指定数据库类型,AI混合方言的概率至少有30%。
四条教训
踩了这么多坑,我总结了几条血泪教训:
1. AI的SQL永远先过脑子再过数据库
现在我养成了一个习惯:AI生成的SQL,我不会直接运行。我会先看三样东西:
- JOIN条件:有没有漏条件?条件是否足够精确?
- 聚合逻辑:GROUP BY是否正确?DISTINCT是否必要?
- NULL和边界值:有没有除零、NULL拼接、类型转换问题?
2. 给AI的prompt要「加量加料」
早期的prompt是:
写一个SQL查上个月的订单数据
现在的prompt是:
数据库:MySQL 8.0
表结构:orders(id, user_id, amount DECIMAL(10,2), status VARCHAR(20), created_at DATETIME)
索引:orders_created_at_idx
数据量:约500万行
需求:查上个月的订单总数、总金额、平均客单价、以及每日趋势
注意:amount可能为NULL,请处理;只取status='completed'的订单
请用CTE而非子查询,避免嵌套过深
细节越多,质量越高。
3. 建立SQL Review清单
我建了一个Markdown checklist,每次Review AI生成的SQL时逐项核对:
- [ ] 所有字段来源于正确的表
- [ ] JOIN条件完整无遗漏
- [ ] GROUP BY包含所有非聚合SELECT列
- [ ] NULL值处理得当
- [ ] 数据类型转换正确
- [ ] 时间范围考虑了时区和边界值
- [ ] WHERE条件能利用索引
- [ ] 没有SELECT *
- [ ] 大数据量查询用了limit/分页
4. 让AI自己Review自己
一个最近发现很有用的技巧:让AI生成SQL之后,再让同样的AI去检查自己的SQL。
刚才你生成的SQL,请逐行review:
1. 是否存在潜在的性能问题?
2. 是否有逻辑漏洞?
3. 能否写出更优版本?
AI往往能发现自己的问题——因为它「看到」的是完整的文本,而生成时是逐token生成的,容易局部失明。多次生成+交叉验证,质量可以提升很多。
什么时候可以信任AI写的SQL?
半年下来,我认为AI写SQL的可靠性分场景:
| 场景 | AI可靠度 | 我的做法 |
|---|---|---|
| 简单CRUD | ★★★★★ | 直接信任,快速检查 |
| 单表聚合查询 | ★★★★☆ | 检查聚合逻辑 |
| 多表JOIN(2-3张) | ★★★☆☆ | 仔细Review JOIN条件 |
| 复杂分析查询 | ★★☆☆☆ | 逐个CTE验证,小数据先跑 |
| 生产DDL/数据变更 | ★☆☆☆☆ | 手写为主,AI只辅助 |
下一步:AI写SQL会替代数据开发者吗?
说了这么多翻车案例,你可能觉得我在黑AI。其实恰恰相反——我现在80%的SQL都由AI生成。
关键词是「生成」,不是「无脑用」。
AI是一个极其高效的初稿生成器,但还不是一个可靠的最终交付者。它把以前需要8小时完成的工作压缩到了2小时,但那剩下的1小时必须用来Review、测试和优化。
2026年的AI写SQL,就像一个极其聪明但不接地气的新人同事——思路开阔、效率极高,但缺乏实战经验,不知道哪些代码会炸、哪些边界情况要考虑。
我们的工作不是「让AI代替自己写SQL」,而是「成为那个给AI兜底的人」。
半年过去了,我的BI项目没有宕机,数据没有出过大错,团队效率提升了2-3倍。这些翻车经历,现在回头看都是宝贵的教训。
以后AI写SQL的能力肯定会越来越强,但现在,每一次我按下「执行」按钮之前,都会再问自己一句:AI写的这条SQL,我真的看懂了么?
如果答案是「是」,那么运行它。如果答案是否定的,那就再看一遍。
💬 评论
0