Text to SQL:为何被标记为 Hold,以及应该如何安全使用
Brief
Text to SQL 使用大模型将自然语言转换为可执行的 SQL,但在实际可靠性上明显低于预期。因此,该技术雷达将其调整为 Hold,目的是不鼓励在无人监督的工作流中直接使用。典型高风险场景包括:对用户自然语言查询进行实时转换并直接执行,而结果又被隐藏在后端或后续自动化流程中。
在这类场景下,大模型因为对业务 schema 与领域知识理解有限,容易产生幻觉 SQL,导致错误的数据读取甚至意外的数据修改。再加上大模型输出本身具备非确定性特征,同样输入在不同时间可能生成不同 SQL,使得调试、回溯与审计都变得困难。
因此建议对 Text to SQL 持谨慎态度:所有生成的 SQL 都必须经过人工审查。对于“智能 BI / Agent”类能力,不应让其直接访问生产数据库,而是经由受治理的数据抽象语义层(如 Cube、dbt semantic layer),或使用具有丰富语义约束和访问控制的中间访问层(如 GraphQL、MCP 等)来间接访问数据。
来源:技术雷达
Details
背景与现状:为什么大家都在关注 Text to SQL
自然语言查询数据库的诱惑
- 对业务方和分析师而言,能用自然语言直接问数据库,是一个非常强的“效率叙事”:减少 SQL 学习成本、缩短分析迭代周期。
- 对平台和数据团队而言,Text to SQL 看似可以在不大改现有数据栈的前提下,给应用、BI、运营后台“加一层智能问答”。
实际落地的典型形态
- BI 或分析工具中增加“自然语言查询”入口,通过 LLM 将描述翻译为 SQL,直接跑在数仓或 OLTP/OLAP 数据库上。
- 产品内嵌“智能报表 / 智能问数”能力,对终端用户输入的自然语言进行解析并执行查询。
- 运维或内部工具中,用自然语言生成只读或读写 SQL,辅助排障或批量操作。
这些场景一旦进入“无人监督、自动执行”模式,就触碰到本文强调的风险边界。
问题与风险:为什么被降级为 Hold
核心风险一:有限 schema / 领域理解导致幻觉 SQL
即便提供了数据库 schema 信息,LLM 仍然往往:
- 误解字段语义:例如把“status”当作订单状态而非支付状态,或者混淆多个相似命名字段。
- 编造不存在的表或列:基于训练中见过的模式“脑补”结构,在本业务库中其实不存在。
- 错推业务规则:如错误理解“有效订单”的过滤条件,遗漏多表 join 关系中的关键约束。
在只读查询场景,这常常体现为“看似合理但语义有误”的查询结果:
- 指标偏移、漏数、重复计数等问题,不一定会触发显式报错,但会直接影响决策。
- 如果结果只被用作下游自动化输入(例如驱动业务规则或路由),问题更隐蔽。
在读写场景,风险进一步升级:
- 错误的 where 条件或缺失的限制,可能导致大规模更新/删除。
- 本应只读的查询被误生成为写操作,或对错误的 schema 进行写入。
核心风险二:非确定性使调试与审计变得困难
LLM 输出通常是非确定性的,体现在:
- 相同的自然语言 query,在不同时间或 context 下生成不同 SQL。
- 微小 prompt 变化可能导致 join/过滤条件大幅不同。
这对工程实践带来几个问题:
- Bug 复现困难:同一异常报表或错误数据,很难稳定重放当时的生成 SQL。
- 审计链路缺失:如果不强制记录“原始自然语言 + 最终 SQL + 上下文信息”,难以在事后追责或回溯影响范围。
- 异常监控不敏感:很多逻辑性错误不会触发数据库层面的 error,只会以“结果不对”体现。
模式与原理:Text to SQL 在技术上实际在做什么
本质:从“句子”到“查询计划”的弱约束映射
从抽象视角看,Text to SQL 是:
- 输入:自然语言描述 +(可选)schema 文本/示例 + prompt 约束。
- 输出:SQL 文本,携带隐含的“查询计划”。
LLM 在这里做的主要是模式匹配和语义对齐:
- 基于语料中见过的 SQL 模式,将自然语言需求映射到:
- 表/视图选择;
- 字段与聚合函数;
- join 关系;
- 过滤、排序、分页等操作。
- 对 schema 的“理解”本质上是把 schema 文本作为额外上下文,做软匹配而非严格类型推导。
关键限制:缺乏强类型和逻辑验证
与传统“查询构建器 / ORM / 语义层”不同:
- LLM 生成的 SQL 事前没有类型检查或约束验证:
- 错表、错列、错 join 关系,只能在执行期由数据库抛错,或默默返回错误结果。
- 缺少形式化的业务语义建模:
- 比如“订单生命周期”“合规过滤条件”等通常是散落在提示词、示例和上下文里的最佳实践,而不是可验证的规则。
这决定了:单靠 LLM 直接从自然语言到 SQL,很难达到生产级“可靠查询规划器”的标准。
对比与演进:Text to SQL vs 语义层 / GraphQL / MCP
传统与现代的“语义访问层”模式
相比直接生成 SQL,语义层和中间访问层提供了几个关键特征:
- 明确定义的域模型与度量:如 Cube、dbt semantic layer 中的 metrics、dimensions、entities。
- 可治理的查询接口:GraphQL schema、MCP 工具定义等,以“受控 API”的形式暴露能力。
- 更易审计与演进:接口变更、权限策略、调用日志都可以集中管理。
在这种模式下,LLM 的角色更类似于:
- 将自然语言映射到已有的语义实体与操作(例如“订单数” → metric.orders.count)。
- 组合已有的 API 或查询模板,而非自由编写 SQL。
从“直接 SQL 生成”向“受控语义调用”演进
一个合理的演进路线通常会是:
- 阶段 0:人工 SQL + 规范化数据模型,无 LLM。
- 阶段 1:在分析/BI 工具中,用 Text to SQL 辅助生成人类可读 SQL,由分析师审查后执行。
- 阶段 2:构建或接入语义层,把关键数据访问抽象为 metrics/维度或 GraphQL/MCP 接口。
- 阶段 3:在语义层之上使用 LLM,将自然语言解析为语义查询/接口调用,由后端将其翻译为 SQL。
- 阶段 4:基于调用日志与权限,逐步为部分语义查询开放更高自动化等级,但仍不直接暴露原始数据库写权限。
技术雷达把“Text to SQL”本身标为 Hold,本质上是建议:跳过把“自然语言 -> SQL”当成最终形态,而优先建设语义访问层,再让 LLM 调用该层。
系统影响:对架构、数据治理与工程实践的要求
对整体数据架构与边界的影响
如果不加约束地引入 Text to SQL,常见系统性后果包括:
- 数据访问边界模糊:任何终端能力都有可能在 LLM 的帮助下绕过中间层,直接触碰底层 schema。
- Schema 变更成本上升:数据库结构一旦变化,大量隐式依赖(LLM 生成的 SQL、提示词示例)会在运行时以“软错误”形式爆炸。
- 数据权限模型被绕过:如果 Text to SQL 挂在一个高权限服务上,很难用传统的“按表/按列”权限规则进行有效隔离。
相反,采用语义层或 GraphQL/MCP:
- 可以将“数据库 schema 演化”与“上游调用方协议”解耦。
- 可以在语义实体层面施加权限与审计规则,更贴近业务角色(如“销售只看自己区域的汇总指标”)。
对调试、观测与审计体系的要求
要在任何程度上使用 Text to SQL/LLM 数据访问,要提前考虑:
- 记录完整调用链:
- 原始自然语言输入;
- 生成 SQL 文本;
- 所用 schema 视图/提示词版本;
- 执行结果摘要与错误信息。
- 建立可查询的审计日志:
- 支持按用户、按时间、按表/字段反查对应的 LLM 生成 SQL。
- 设置防御性限流与保护:
- 如自动检测“全表扫描、大范围写操作、无 where update/delete”等危险模式并阻断。
否则,一旦出现“大量错误查询或意外写入”,事后排查和问责将非常困难。
落地建议:如何“谨慎使用”而不是简单弃用
场景划分:哪些地方可以用,哪些地方坚决不要用
更可接受的场景(前提是有人审查):
- 分析师/数据工程师 IDE 或 BI 工具内的SQL 草稿助手:
- 由 LLM 生成初稿,人类在执行前修改与确认。
- 离线/非生产环境的探索性分析:
- 在读副本或脱敏环境中使用,以加速临时数据探索。
- 受限模板内的参数填充:
- SQL 模板由工程师定义,LLM 仅在限定字段/条件空间内填空,而非自由编写完整查询。
高风险、应避免的场景:
- 生产库上的无人监督 Text to SQL,尤其是:
- 用户自然语言 → 直接执行 SQL → 结果驱动业务决策或自动操作;
- 含写操作(INSERT/UPDATE/DELETE/MERGE)的任何自动化链路。
工程与治理层面的最小安全基线
如果团队仍希望在局部试点 Text to SQL/LLM 数据访问,建议至少做到:
- 强制人工 review:任何 LLM 生成的 SQL,在执行前必须由具备相应权限的人明确确认。
- 只读访问、最小权限:
- 在物理上隔离只读节点/视图;
- 在逻辑上确保 LLM 使用的凭证不具备写权限。
- 构建基本的语义/访问抽象:
- 即便暂时不上完整语义层,也可以:
- 为关键数据构建只读视图;
- 封装常用指标与业务过滤条件;
- 让 LLM 主要在这些视图上工作,而不是全库乱跑。
- 即便暂时不上完整语义层,也可以:
- 引入简单的静态规则校验:
- 执行前对 SQL 做规则扫描,拦截危险模式(如无 where 的 delete、对大表的全表更新等)。
面向“Agentic BI”的推荐路径
如果目标是构建较为智能的 BI Agent 或数据助手,结合原文建议,一个更稳妥的路线是:
- 先引入或自建语义层(Cube、dbt semantic layer 或同类能力):
- 把 metrics、维度、业务实体建模清晰;
- 通过一个统一层负责从语义查询到 SQL 的翻译。
- 对外暴露受治理的语义访问接口(GraphQL、MCP 或自定义 API):
- 在这个接口层实现权限、限流与审计能力。
- 让 LLM/Agent 只负责:
- 自然语言 → 语义查询或接口调用;
- 结果解读和对话式呈现。
- 将“自然语言→SQL”视为内部实现细节,不直接暴露给终端 Agent 或用户。
在这个框架下,Text to SQL 不再是一个“独立的生产技术”,而是:
- 语义层和访问层内部可选的实现方式之一;
- 且始终运行在强约束、强审计的环境中。
整体来看,“Text to SQL 被标为 Hold”并不意味着“自然语言数据访问被否定”,而是强调: 直接将自然语言映射到 SQL 并在无人监督下执行,风险远超收益;更合理的方向是在语义层和受治理访问层之上用 LLM 做智能编排和交互。