You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析SQL语句时出现NoViableAltException异常的原因及解决方法

使用ANTLR解析MySQL SQL时遇到NoViableAltException的问题排查与解决

环境与配置

  • Antlr版本:antlr-4.13.1-complete.jar
  • 语法文件:基于MySQL官方ANTLR4语法实现修改,仅新增以下规则处理单字符串多SQL场景:
queryMulti
    : ((simpleStatement | beginWork) SEMICOLON_SYMBOL?)* EOF
    ;
  • 测试SQL语句:
SELECT * FROM table_a AS a INNER JOIN table_b AS b ON a.field_1=b.field_2
  • C#解析代码:
string sql = "SELECT * FROM table_a AS a INNER JOIN table_b AS b ON a.field_1=b.field_2";

ICharStream charStream = CharStreams.fromString(sql);
ITokenSource lexer = new MySQLLexer(charStream);
ITokenStream stream = new CommonTokenStream(lexer);
MySQLParser parser = new MySQLParser(stream);
parser.AddErrorListener(new MySQLParserErrorListener());
var treeAll = parser.queryMulti();

异常信息

15:18:48 Error: no viable alternative at input 'SELECT * FROM table_a AS a INNER JOIN table_b AS b ON aS.field_1' - Loc[1(55)] - Antlr4.Runtime.NoViableAltException: Exception of type 'Antlr4.Runtime.NoViableAltException' was thrown.
   at Antlr4.Runtime.Atn.ParserATNSimulator.ExecATN(DFA dfa, DFAState s0, ITokenStream input, Int32 startIndex, ParserRuleContext outerContext)
   at Antlr4.Runtime.Atn.ParserATNSimulator.AdaptivePredict(ITokenStream input, Int32 decision, ParserRuleContext outerContext)
   at WPF_DbTools.Antlr.MySQLParser.selectStatement() in dir\MySQLParser.cs:line 15862
exception:"Antlr4.Runtime.NoViableAltException"(in Antlr4.Runtime.Standard.dll)

问题分析与解决

1. 异常信息中的'S'并非解析失败原因

这个额外的'S'是ANTLR错误信息的显示bug——它错误拼接了前面AS关键字的最后一个字符与后续标识符a,原SQL实际是AS b ON a.field_1,不存在aS这个输入,只是错误输出时的字符拼接问题。

2. 真正的失败原因与修复方向

  • 规则范围不匹配:新增的queryMulti规则调用了simpleStatement,需确认原MySQL语法中simpleStatement是否包含selectStatement分支。如果原语法中SELECT语句不属于simpleStatement的覆盖范围,解析时就会因找不到匹配规则抛出NoViableAltException。
  • 规则逻辑调整:
    • 直接改用原语法的顶层语句规则(如statement)来覆盖所有SQL类型,修改queryMulti规则:
      queryMulti
          : (statement SEMICOLON_SYMBOL?)* EOF
          ;
      
    • 若需保留原有分支,补充selectStatement到可选规则中:
      queryMulti
          : ((simpleStatement | selectStatement | beginWork) SEMICOLON_SYMBOL?)* EOF
          ;
      
  • 验证基础规则:先单独调用parser.selectStatement()解析测试SQL,确认原语法本身能正确处理该语句,再排查queryMulti规则的集成问题。
  • 重新生成代码:修改语法文件后,务必重新生成词法、解析器代码,确保规则生效。

内容的提问来源于stack exchange,提问作者hchlqlz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:27:17