《SQL必知必会》学习随笔:Text to SQL 与行业实战
前言
专栏在完结多年后又增加了几篇加餐,主要分成两类内容:
- Text to SQL:使用自然语言生成 SQL;
- 行业实战:银行、保险、证券、新能源车企和快消场景中的查询与优化。
行业实战部分已经写得很具体,我就不重复搬运原文了。这篇主要整理 Text to SQL 的思路,并补充一些我认为真正落地时必须注意的问题。
Text to SQL 是什么
Text to SQL,简单来说就是把自然语言问题转换成 SQL 查询。
例如用户提出:
查询最近 30 天销量最高的 10 个商品,并显示商品名称和销售额。
模型需要先理解“最近 30 天”“销量最高”“销售额”等业务含义,再结合数据表、字段、关联关系和数据库类型,生成可以执行的 SQL。
它降低了 SQL 的使用门槛,但不意味着完全不需要懂 SQL。特别是涉及复杂查询、权限控制、性能优化和数据修改时,最终仍然需要有人检查生成结果。
不要只看模型榜单
原内容列举了当时常见的闭源模型、开源模型和代码模型。但模型版本更新很快,半年后榜单可能就已经没有参考价值了,所以这里不再按名称排一个容易过时的名次。
如果要选择 Text to SQL 模型,我更关心下面几点:
- Schema 理解能力:能否理解表结构、主外键、字段注释和业务含义;
- 复杂查询能力:能否正确生成多表连接、聚合、窗口函数和子查询;
- 方言支持:是否知道 MySQL、PostgreSQL、SQL Server 等数据库的语法差异;
- 结构化输出能力:能否稳定地只返回 SQL 或指定 JSON,而不是夹杂大段说明;
- 上下文长度与成本:面对大量表结构时,能否在成本可接受的情况下完成任务;
- 本地部署需求:敏感数据是否允许发送到外部服务。
对实际项目来说,用自己的数据库问题做一套测试集,通常比只看公开榜单更可靠。
Text to SQL 的完整流程
如果只是把一句自然语言和整个数据库结构一起丢给模型,简单问题可能能用,但表一多,准确率就会明显下降。
我目前理解的完整流程如下:
- 理解用户问题:识别指标、维度、筛选条件、时间范围和排序要求;
- 检索相关 Schema:只找与当前问题有关的表和字段,而不是把整个数据库全部塞进去;
- 补充业务语义:说明“有效订单”“销售额”“新增用户”等业务概念如何计算;
- 生成 SQL:明确数据库方言,并限制输出格式;
- 静态校验:检查表名、字段名、语法、危险语句和权限范围;
- 试执行或解释执行计划:优先使用只读账号,必要时先执行
EXPLAIN; - 根据错误修正:把数据库返回的错误信息交给模型进行有限次数的修复;
- 返回结果与说明:除了查询结果,还应说明口径和可能存在的限制。
这套流程中,真正困难的往往不是“写出一条看起来像 SQL 的字符串”,而是找到正确的表、理解业务口径,并保证执行安全。
提示词应该提供什么
原文给出了三种提示词。核心结论是:与一段模糊的中文表说明相比,结构化的建表语句通常能给模型更多信息。
我认为一个比较实用的提示至少应包含:
- 数据库类型和版本;
- 相关表的 DDL;
- 字段注释和枚举含义;
- 表之间的关联关系;
- 用户问题;
- 输出格式;
- 安全限制;
- 必要时提供一两个相似示例。
可以写成下面这样:
1 | 你是一名 SQL 助手,请根据给定的数据库结构生成查询。 |
这里的 create_sql 不只是表名列表,最好包含字段类型、主键、外键、唯一约束和注释。因为这些信息能帮助模型判断字段用途,也能减少编造不存在字段的情况。
为什么“只给 DDL”仍然不够
DDL 适合描述数据库结构,但它不一定能表达业务语义。
例如订单表中可能同时存在:
created_at:订单创建时间;paid_at:支付时间;finished_at:完成时间;cancelled_at:取消时间。
用户问“本月订单量”时,到底应该使用哪个时间字段?只看 DDL 很难确定。因此在真实项目中,还需要补充指标定义、字段说明,或者让模型在不确定时先追问。
另一个问题是表太多。假设数据库中有几百张表,把所有 DDL 都放进提示词不仅浪费上下文,还会增加模型选错表的概率。更合理的方式是先检索相关表,再生成 SQL,也就是把问题拆成“找表”和“写 SQL”两个阶段。
安全问题比生成能力更重要
Text to SQL 最危险的地方,不是 SQL 写错后报语法错误,而是它能够执行,但查询口径错误、扫描数据过多,甚至修改了不该修改的数据。
我认为至少要做下面几层限制:
使用只读账号
面向查询的 Text to SQL 服务不应该连接拥有写权限或 DDL 权限的数据库账号。即使提示词要求“只生成 SELECT”,也不能把安全完全寄托在模型听话上。
限制语句类型
在执行前解析 SQL,只允许 SELECT、WITH 和必要的解释语句。不能只用简单的字符串包含判断,因为注释、大小写和嵌套语法都可能绕过这种检查。
控制查询成本
可以设置超时时间、最大返回行数和资源限制。对可能扫描大量数据的语句,先使用 EXPLAIN 检查执行计划。
记录审计日志
保留用户问题、模型生成的 SQL、执行结果、耗时和错误信息。后续出现问题时,至少能够知道是哪一步出了错。
如何评估生成质量
只看 SQL 能不能执行是不够的。一条 SQL 即使语法正确,也可能回答了另一个问题。
可以从下面几个角度评估:
| 维度 | 需要检查的问题 |
|---|---|
| 可执行性 | SQL 是否能够在目标数据库中执行 |
| 结果正确性 | 返回结果是否符合预期口径 |
| Schema 一致性 | 是否使用了真实存在的表和字段 |
| 安全性 | 是否包含越权查询或危险操作 |
| 性能 | 是否出现不必要的全表扫描、笛卡尔积或重复子查询 |
| 稳定性 | 同类问题换一种说法后,结果是否仍然正确 |
如果准备把 Text to SQL 用到正式项目,最好先收集一批真实问题和标准 SQL,做成固定测试集。每次更换模型、提示词或 Schema 检索方式后都重新跑一遍,才能知道效果到底变好了还是变差了。
加餐 02~06:行业查询与优化
这部分主要是原作者从真实开发场景中提炼的经验,针对性很强。我想了一下,原文已经整理得比较精简,我就不班门弄斧了,直接把对应链接列出来,请有需要的朋友自行查看。