过去一个月,我做了个实验:把日常的数据分析需求,尽量交给大模型写 SQL,看看它到底靠不靠谱。
结论有点扎心:大模型写 SQL,最擅长的不是"写对",是"看起来对"。
它生成的 SQL,语法工整、注释齐全、格式漂亮,一眼看过去专业得不行。但你真拿去跑,十个里能有三四个是错的——而且错得特别隐蔽,不仔细核对根本发现不了。
这篇文章记录我踩过的坑,以及"大模型写 SQL"这件事的边界到底在哪。
先说它做得好的地方,不然显得我不客观。
大模型写 SQL 的"卖相"是真的好。你给它一句需求,它秒回一段:
sql复制-- 统计各品类近30天的销售额及环比增长率
SELECT
c.category_name,
SUM(o.order_amount) AS total_sales,
ROUND(
(SUM(o.order_amount) - LAG(SUM(o.order_amount)) OVER (PARTITION BY c.category_name ORDER BY month))
/ LAG(SUM(o.order_amount)) OVER (PARTITION BY c.category_name ORDER BY month) * 100,
2
) AS mom_growth_rate
FROM orders o
JOIN categories c ON o.category_id = c.category_id
WHERE o.order_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY)
GROUP BY c.category_name
ORDER BY total_sales DESC;语法正确、缩进规范、还贴心地加了注释。要是让一个新手数仓工程师写,都不一定写得这么"像样"。
问题就出在这个"像样"上。 它太像那么回事了,以至于你会下意识地放松警惕——"写得这么专业,应该没问题吧?"
然后你就被坑了。
我把这一个月里大模型犯的错归了归类,发现一个共同点:这些错误,语法上全是对的,逻辑上全是错的。
上面那段 SQL,仔细看 LAG(...) OVER (PARTITION BY ... ORDER BY month)——它按 month 排序,但 WHERE 条件里又限定了"近 30 天",而且 GROUP BY 是按 category_name 聚合的,month 字段根本没出现在 GROUP BY 里。
这段 SQL 在 MySQL 里可能直接报错(month 不在 GROUP BY 里),在 Hive 里可能返回莫名其妙的结果。但如果你不仔细看逻辑,光看语法,它"看起来"完全正确。
大模型特别擅长犯这种"语法对、语义错"的错误。 因为它学的是"SQL 长什么样",不是"SQL 到底在算什么"。
我让它写一个"统计每个用户的订单数",它写:
sql复制SELECT u.user_id, COUNT(o.order_id) AS order_count
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
LEFT JOIN order_items oi ON o.order_id = oi.order_id
GROUP BY u.user_id;问题在哪?orders 和 order_items 是一对多关系,一个订单有多个商品明细。LEFT JOIN order_items 之后,订单数被重复计算了——一个订单有 3 个商品,就被算了 3 次。
这个错误,语法上挑不出任何毛病,但结果就是错的。而且错得特别隐蔽——如果你不核对具体数字,光看"订单数"这个字段名,你根本想不到它算重了。
我让它统计"本月的数据",它写:
sql复制WHERE order_date >= DATE_FORMAT(CURRENT_DATE, '%Y-%m-01')看起来对,对吧?"本月初至今"。但问题是,如果今天是 1 号,CURRENT_DATE 就是本月 1 号,这个条件没问题。但如果业务上"本月"指的是"自然月",那月初的数据可能还没跑完,统计出来的数是不完整的。
这种"边界情况"的坑,大模型几乎必踩。因为它不会主动问你"你说的本月,是指自然月还是滚动 30 天?",它只会选一个"看起来合理"的解释,然后写给你。
最离谱的一次,我让它统计"客户流失率",它写了一段 SQL,把"流失"定义成了"最近 30 天没有下单"。
这个定义本身没错,但问题在于,我们业务上的"流失"定义是"连续 90 天没有下单"。它没问我,直接用了"30 天"这个它觉得合理的默认值。
大模型对"业务语义"的理解,永远停留在"通用常识"层面,它不知道你们公司的"流失"到底怎么定义。 而这类业务口径,恰恰是 SQL 能不能写对的关键。
深挖一下,大模型写 SQL 容易错,根源有三个。
第一,它不懂数据。
大模型写 SQL,靠的是"见过海量 SQL 语料",不是"理解你的数据"。它不知道你的 orders 表和 order_items 表是什么关系,不知道 amount 字段是含税还是不含税,不知道"流失"在你们公司怎么定义。它只能猜,而猜就一定会猜错。
第二,它不会验证。
人写 SQL,写完会跑一下、看看结果、对对数。大模型写 SQL,写完就交给你了,它不跑、不验、不核对。它对自己写的东西"盲目自信",哪怕逻辑是错的,它也会用"专业"的语气告诉你"这段 SQL 是对的"。
第三,它太会"装"了。
这是最要命的一点。大模型的语言能力太强,强到它能把一段逻辑错误的 SQL,包装得"看起来无比正确"。语法工整、注释清晰、命名规范——这些"表面功夫"做得越好,你越容易放松警惕,越容易被坑。
能,但要用对姿势。我的经验是三条。
第一,让它写"骨架",你来填"业务"。
大模型擅长的是"SQL 的写法"——语法、函数、JOIN、窗口函数这些技术细节。它不擅长的是"业务语义"——口径、定义、边界条件。
所以正确的用法是:你告诉它业务口径("流失是连续 90 天没下单"),让它写技术实现("用窗口函数还是子查询")。把业务定义这件事牢牢抓在自己手里,只把"怎么写"交给它。
第二,永远假设它是错的,跑一遍再信。
大模型写的 SQL,我默认它是错的,跑一遍、对对数、看看结果合理不合理,确认无误才敢用。这不是不信任它,是尊重它的"犯错概率"。
第三,让它写"简单 SQL",复杂逻辑自己来。
大模型写单表查询、简单 JOIN、基础聚合,准确率还可以。但一旦涉及多表关联、复杂窗口函数、嵌套子查询、业务口径,它的准确率就断崖式下降。
我的经验是:能一句话说清楚的查询,交给它;需要理解业务逻辑的查询,自己写。
实验做完,我得出一个更本质的判断:大模型写 SQL 的问题,不是"技术不行",是"没有上下文"。
它写错,不是因为它不会 SQL,是因为它不知道你的数据长什么样、你的业务怎么定义、你的口径是什么。
这其实指向了一个方向:如果能把"数据上下文"喂给大模型——表结构、字段含义、业务口径、数据血缘——它的准确率会大幅提升。
这也就是为什么"大模型 + 数据治理"是个有前途的方向。数据治理做得好,元数据、数据字典、业务口径都梳理清楚了,大模型写 SQL 就有了"上下文",不再是"瞎猜"。
大模型写 SQL 的准确率,上限不取决于模型,取决于你的数据治理水平。
大模型写 SQL,最危险的不是它"写不对",而是它"看起来对"。
语法工整、注释齐全、格式漂亮,这些"表面功夫"会麻痹你的警惕,让你忘了去核对逻辑。而它犯的错,恰恰全是"语法对、语义错"的隐蔽错误。
所以,如果你也在用大模型写 SQL,记住一句话:把它当"实习生",别当"专家"。 它写的代码,你可以参考,但必须自己验证。它给的答案,你可以参考,但必须自己判断。
"看起来对"和"真的对",中间隔着一整个数据治理的距离。
本文基于作者一个月的大模型写 SQL 实验写成。文中 SQL 示例为脱敏后的简化版本,实际错误类型更多样。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。