I反对生成式 SQL 的理由
模型不应该
编写 SQL。
Text-to-SQL 是将 Agent 接入数据库的直观方式,演示效果确实令人印象深刻。但问题在生产环境中才会显现:同一个问题编译出不同的 SQL,一个隐蔽的 join 错误让收入偏移 15%,而模型的输出也成了攻击面。还有另一条路。
II先给予肯定
Text-to-SQL 名副其实——在其适用范围内。
适用场景
- 基于临时数据的原型验证
- 在人工监督下探索陌生 schema
- 有人会事后核验的一次性问题
- 演示场合——效果确实出色
失效场景
- 将被直接用于决策的数字
- 上下文中存在任何不可信文本
- 连接使用生产环境凭据
- 需要可复现或可审计的结果
- 无人监督运行的 Agent
问题不在于这种模式本身,而在于其爆炸半径。本页所有风险都源于同一个设计决策:模型的输出被当作代码执行。
III两条路径
同一问题,两种架构。
跟随同一个问题走过两条路径——左侧是自由格式 SQL 字符串,右侧是类型化执行计划。编号标记对应下方的风险台账。
“哪个地区的总收入最高?”
模型提交类型化计划
- 类型化意图
不是字符串,而是带有 schema 的值。它只能声明契约所定义的操作。
{ "kind": "query", "version": "1", "source": "revenue", "op": "sum", "group_by": "region" } - 契约校验
哈希锁定。未知操作返回
unsupported_operation及最近匹配项——绝不猜测。 - 策略校验
代码层面的允许列表。请求只能缩小操作范围,不能扩大。
- 确定性执行
float64、单线程、固定运行时。相同计划,相同字节,相同结果。
east · 2130.50
plan_hash f87610d8afeb…
decision_path "exact_spec"
唯一结果,附带可供复现的哈希值——下周、下季度,两种语言均适用。
IV风险台账
生成式 SQL 的五类失效
- 01
P2SQLarXiv 2308.01990
注入攻击转移至输出通道
输入过滤检查的是进入模型的内容。P2SQL 攻击发生在输出端:格式合法、意图恶意的 SQL,由隐藏在用户消息或检索行中的指令拼装而成。任何输入过滤器都看不到它——攻击本身就是输出。
- 02
−15%那个说谎的仪表盘
错误关联静默失效
扇出关联导致行被重复计数,收入数字偏差 15%。没有异常,没有警告——错误的 SQL 不会崩溃,只会照常上报。结果永远是一个数字,而一个看似合理的数字不会透露任何错误信号。
- 03
1 → n一个问题,n 条查询
同一问题,不同 SQL
问两次,模型可能以两种不同方式编译这个问题——有时得出两个不同答案。没有可供审查、缓存或复现的规范查询。昨天的数字无法再现,哪怕只是为了核验。
- 04
91.2 → 21.3正确率 · 基准测试 → 企业 schema
精度断崖
在整洁的基准 schema 上,前沿模型生成正确 SQL 的概率为 91.2%。在真实企业 schema 上:21.3%。同一研究中,约 40% 的 text-to-SQL Agent 运行彻底失败或返回错误结果。基准测试是干净的,你的 schema 不是。
- 05
1 个生产数据库被 agent 删除——Replit 事件
写入路径从未消失
Replit 的编程 agent 无视明确禁令,删除了一个生产数据库。教训在此:只读指令不过是一句请求。连接若能写入,写入路径便始终存在,终有一次错误补全会找到它。只读必须是工具本身的属性,而非 prompt 里的一行字。
不要过滤输出。
不要生成它。
无 SQL 字符串,无注入 · 无猜测,无漂移
V证书
五个维度,并排对比
非 LLM 转 SQL 生成器引擎 README
差异证书
右列已锁定至合约sha256:79f1c5a6…924be9a1
细则经得起推敲:引擎唯一的逃生舱——getUnsafeRuntime——在所有面向模型的界面中均不存在,模型无从触及。README 亦明确声明:这不是 LLM 转 SQL 生成器。
VI常见问题
生产环境中的追问
如何在 LLM 生成的 SQL 中屏蔽 DELETE 和 DROP?
不要过滤 SQL——停止生成它。黑名单检查的是字符串,而模型在生成新字符串方面永无止境。SQAI 从根本上消除这一类问题:模型针对 4,574 项只读能力提交类型化计划,任何计划都无写入能力可调用。
什么是 P2SQL 注入?
Prompt 转 SQL 注入:恶意 SQL 出现在模型的输出中,由模型所读取内容中隐藏的指令拼装而成——可能来自用户消息、文档或检索到的数据行。输入过滤对此无能为力,因为攻击发生在输出通道。相关记录见 arXiv 2308.01990。
文本转 SQL 是否有适用场景?
有——在非生产数据上做原型验证或有监督的探索时,它快速且切实有用。但一旦结果将被付诸行动、上下文包含不可信文本,或答案需要可重现,它便不再是正确选择。
如何为 AI agent 提供对数据库的只读访问?
让只读成为结构性约束,而非配置项。连接上的只读标志是一个随时可被更改的设置。SQAI 的执行界面仅包含读取能力——写入路径从构造上不存在,即便是引擎的逃生舱,任何面向模型的工具也无从触及。
类型化计划与生成的 SQL 有何不同?
SQL 字符串可以表达语法所允许的任何内容。类型化计划只能表达合约所定义的内容。每个计划都经过哈希锁定合约的验证、白名单策略的检查,并在确定性引擎上执行——每条结果附带重放哈希。