← 数据分析 Agent

SQL 执行报错后,怎么让大模型自动纠错?

高频 中等 SQL 执行失败自动纠错 · 第 1 / 2 问 更新于 2026/09/29
Text-to-SQLSQL纠错数据分析Agent自愈
本题落地项目AI Agent数据分析平台

简化版

把原 SQL、数据库返回的具体报错、表结构上下文(最好再加上用户的原始问题)一起交给模型,让它返回修正后的 SQL 和修改理由,然后重新走一遍安全校验再执行。有三个关键点:报错要取最内层的数据库异常(Unknown column 'u.user_id' in 'on clause'),而不是框架包装后的 bad SQL grammar;纠错要有次数上限,通常一次;纠错之后,旧 SQL 的执行结果、图表、解读要全部作废,避免新 SQL 配旧结论。

详细版

纠错流程:

执行报错
  → 沿异常链取到最底层的数据库报错
  → 组装纠错 Prompt:原问题 + 原 SQL + 报错 + 表结构
  → 模型返回 { sql, fixReason }
  → 保存修正 SQL 和理由(保留原 SQL 与原报错)
  → 旧的执行结果、图表、解读失效
  → 修正 SQL 重新走安全校验 → 执行
      ├─ 成功:展示结果
      └─ 失败:记录新报错,不再自动重试

适合交给模型纠错的错误:字段名或表名写错、别名引用错误、group by 不完整、函数方言不兼容、类型不匹配。不适合纠错的:权限不足、超时、连接失败(这些不是 SQL 写法的问题),以及「没报错但口径错了」的语义问题(没有报错信息可供纠正)。

完整版教学

一、为什么模型能改好自己写错的 SQL

Text-to-SQL 最常见的错误并不复杂:字段名差一个字母、把外键当成了对方表的主键、group by 漏了一列。这类错误的共同点是数据库会给出精确的报错,比如:

Unknown column 'u.user_id' in 'on clause'
Expression #2 of SELECT list is not in GROUP BY clause

报错信息本身就指明了「哪里错、错成什么样」。把它和表结构一起交给模型,相当于给了它一次带答案提示的重试机会。这种「执行 → 拿到真实反馈 → 修正」的闭环,比一开始就要求模型一次写对要现实得多,也是很多 Agent 自愈设计的基本思路。

二、报错信息一定要取最内层

Java 的数据访问框架会把数据库异常一层层包装。直接取最外层的消息,拿到的往往是:

外层:bad SQL grammar [select ... ]; nested exception is ...
最内层:Unknown column 'u.user_id' in 'on clause'

「bad SQL grammar」只说明 SQL 有语法问题,模型拿到它只能瞎猜;最内层才告诉它是 u.user_id 这一列不存在。所以保存错误时要沿着 getCause() 一路找到最底层的异常:

// 沿异常链找到最底层的数据库异常,它才包含具体的出错位置
Throwable cause = e;
while (cause.getCause() != null && cause.getCause() != cause) {
    cause = cause.getCause();
}
String errorMessage = cause.getMessage();

易错点:纠错效果差,第一个要检查的就是交给模型的报错是不是最内层的那一条。

三、纠错 Prompt 要给哪些东西

输入作用缺了会怎样
原 SQL在它的基础上改模型重写一条全新的 SQL,可能引入新错误
数据库报错指出具体错在哪模型只能猜
表结构上下文知道正确的字段名和关联关系改完还是错
用户原始问题保证修正后仍然回答同一个问题为了能跑通,悄悄改掉了查询意图

最后一项容易被忽略。模型纠错时的目标是「让 SQL 能执行」,如果不知道原问题,它可能用删掉条件、换一张表的方式让 SQL 跑通,结果回答的已经不是用户问的问题了。输出同样要求结构化:sql 加上 fixReason,修改理由展示给用户,方便判断改得对不对。

四、次数上限:为什么通常只纠一次

纠错可以无限循环吗?不应该。原因有三:

成本   每次纠错都是一次模型调用,加一次数据库执行
收益   一次纠错能解决大部分「写错字段名」这类简单错误;
       一次没改好,多半是理解层面的问题,再改几次也难
风险   反复纠错可能在「错误 A」和「错误 B」之间来回震荡

所以常见的设计是自动纠错最多一次,还失败就把最终报错展示给用户,由人来决定是改问法还是重新生成。需要人工触发时,也可以让用户再点一次纠错,但每一次都要保存当次的报错和修正,便于回看。

五、纠错后要清理什么

修正后的 SQL 是一条新 SQL,和它相关的旧产物都要作废:安全校验状态、查询结果、执行耗时、错误信息、结果摘要、图表配置、数据解读、推荐追问。不清理就会出现页面上显示的是新 SQL,下面的图表和解读却来自旧 SQL 的情况,用户完全看不出来。同时要保留纠错前的原件:原 SQL 和原报错存到单独的字段,修正 SQL 和修改理由另存,这样事后能说清楚「最初写成什么样、因为什么报错、改成了什么」。

六、哪些错误不该交给模型纠

错误类型例子该怎么处理
写法错误字段不存在、group by 不完整、函数不兼容交给模型纠错
安全校验不通过查了白名单外的表、包含危险关键字不纠错,写法本身不合规,重试多半还是同样的问题
权限 / 超时 / 连接无权限、执行超时、数据库连接断开不纠错,这不是 SQL 写法问题,应提示用户或运维
语义错误SQL 能跑,但口径错了没有报错可供纠正,要靠元数据约束和结果核对

把「不该纠」的情况排除掉,纠错这一步才不会浪费调用,也不会掩盖真正的问题。

七、纠错与 Agent 的关系

在多步分析的 Agent 里,某一步 SQL 执行失败时,最自然的处理就是自动触发一次纠错,而不是直接把整个步骤判失败:

第 1 次:生成 SQL → 校验 → 执行 → 报错
第 2 次:纠错 → 校验 → 执行
  成功 → 继续图表、解读
  失败 → 这一步标为执行失败,记录最终报错

这就是 Agent 的「观察 → 修正」能力的一个具体落地,也是为什么纠错要设计成可以被其他流程复用的独立能力。

八、常见误区与追问

  • 误区:把框架抛出的异常消息直接交给模型就行。 外层往往只有 bad SQL grammar 这种笼统信息,要沿异常链取最内层的数据库报错。
  • 误区:纠错可以一直重试,直到成功为止。 一次没改好多半是理解问题,反复重试成本高还可能来回震荡,通常只自动纠一次。
  • 误区:纠错只需要原 SQL 和报错。 还要给表结构,最好给原问题,否则模型可能为了能跑通而改掉查询意图。
  • 误区:纠错之后旧的图表和解读还能继续用。 修正后的 SQL 结果可能完全不同,旧的执行结果、图表、解读都要作废。
  • 误区:所有执行失败都应该纠错。 权限、超时、连接问题和安全校验失败都不是写法问题,交给模型纠错只会浪费调用。
  • 追问:纠错后的 SQL 还要再做安全校验吗? 必须要,修正后的 SQL 是模型新生成的内容,和第一次一样不可信。
  • 追问:怎么评估纠错功能的效果? 统计纠错触发率和纠错后成功率,触发率高说明上下文或元数据有问题,应该从源头改。

九、加强记忆

SQL 执行报错是模型能拿到的最精确的反馈,纠错就是把原 SQL、最内层数据库报错、表结构和原问题交给模型,返回修正 SQL 和理由,再重新校验执行。报错一定取异常链的最底层,笼统的 bad SQL grammar 没用;原问题要带上,防止模型为了跑通改掉意图。纠错设上限,通常只自动一次,失败就交给人;纠错前留原件,纠错后旧的结果、图表、解读全部作废。安全校验失败、权限、超时、连接问题和语义错误都不该交给模型纠。在 Agent 里,纠错是单步失败后的自愈手段,所以要做成独立可复用的能力。

项目实战落地

项目里怎么做的

《AI Agent数据分析平台》把纠错做成了分析记录上的一个「纠错」按钮:

  • 执行失败时保存最内层报错:执行 SQL 的地方捕获异常后,沿 getCause() 找到最底层的数据库异常,比如 Unknown column 'u.user_id' in 'on clause',写进 analysis_query.error_message,状态记为「执行失败」;
  • 纠错:用户点「纠错」后,后端要求这条记录同时有 generated_sql 和 error_message,按「SQL 分析」用途选模型,用 SQL纠错 模板把 {originSql}、{errorMessage}、{datasetSchema} 填进去,要求模型只返回包含 sql 和 fixReason 的 JSON;
  • 保存与失效:修正结果写进 corrected_sql、correction_reason、raw_correction_response,同时把 generated_sql 更新为修正后的 SQL,旧的安全状态、查询结果、执行耗时、错误信息、结果摘要、图表、解读和推荐追问全部清空,状态记为「已纠错」;
  • 自动重新执行:前端拿到纠错结果后,自动调用一次执行接口,重新走安全校验和查询。

在 Agent 多步执行里,这套纠错能力被直接复用:某一步第一次校验或执行失败,后台自动纠错一次再重试,仍然失败才把这一步标为「执行失败」。

为什么这样取舍

  • 手动触发纠错:用户能先看到失败原因,再决定要不要让模型改,纠错过程在页面上完整可见。
  • Agent 里自动纠错只重试一次:后台执行没有人盯着,重试必须有上限,避免错误 SQL 造成无限循环。

面试官还会追问

  • 纠错后的 SQL 再执行一次还是失败,页面会怎样?用户还能再纠错吗?
  • 后端为什么要求 generated_sql 和 error_message 同时存在才允许纠错?

学完《AI Agent数据分析平台》,上面这些追问你都会迎刃而解。

本题落地项目登峰造极AI Agent数据分析平台基于Agent、Text-to-SQL和安全查询执行,实现数据集管理、指标口径维护、分析意图识别、SQL纠错、图表推荐、数据解读和报告生成,适合BI分析落地、过程追踪和多轮会话。SpringbootSpringAIAgentText-to-SQLLLM源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目