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

.NET 6中TSqlParser校验SQL异常,随机字符串被误判为合法

SQL语法验证误判问题的解决方案

问题场景

你当前使用Microsoft.SqlServer.TransactSql.ScriptDom实现的SQL验证函数,能正确识别"Select From XYZ"这类错误语句为无效SQL,但会把"sdcsdcsdcsdcsjnjkc"、"csdcsdc sdcsdcsdc"这类随机字符串判定为合法SQL,需要修正这个误判问题。

你的现有实现代码:

using Microsoft.SqlServer.TransactSql.ScriptDom;
using ParseError = Microsoft.SqlServer.TransactSql.ScriptDom.ParseError;

namespace QueryStore.Application.Utils;

internal static class SqlParser
{
    internal static List<string>? Parse(string sql)
    {
        var parser = new TSql100Parser(false);
        parser.Parse(new StringReader(sql), out IList<ParseError> errors);
        return errors is not { Count: > 0 } ? null : errors.Select(error => error.Message).ToList();
    }
    
    internal static bool BeValidSqlQuery(string content)
    {
        var result = SqlParser.Parse(content);
        return result is null;
    }

}

一、修正现有TSqlParser的验证逻辑

TSql100Parser默认会把孤立的标识符或标识符组合当作合法的批处理语句(比如单独的变量名、存储过程名),所以需要额外校验解析后的语法树是否包含有效的查询语句(如SELECT/INSERT/UPDATE/DELETE等)。

修改后的代码示例:

using Microsoft.SqlServer.TransactSql.ScriptDom;
using ParseError = Microsoft.SqlServer.TransactSql.ScriptDom.ParseError;
using System.IO;
using System.Linq;

namespace QueryStore.Application.Utils;

internal static class SqlParser
{
    internal static List<string>? Parse(string sql)
    {
        var parser = new TSql100Parser(false);
        using var reader = new StringReader(sql);
        var fragment = parser.Parse(reader, out IList<ParseError> errors);
        
        // 先检查语法错误
        if (errors.Any())
        {
            return errors.Select(error => error.Message).ToList();
        }
        
        // 再检查是否包含有效的查询语句节点
        var hasValidQuery = CheckForValidQuery(fragment);
        return hasValidQuery ? null : new List<string> { "输入不是有效的SQL查询语句" };
    }
    
    internal static bool BeValidSqlQuery(string content)
    {
        var result = SqlParser.Parse(content);
        return result is null;
    }
    
    private static bool CheckForValidQuery(TSqlFragment fragment)
    {
        var visitor = new QueryStatementVisitor();
        fragment.Accept(visitor);
        return visitor.HasValidQuery;
    }
    
    // 自定义语法树访问器,过滤出有效的查询语句类型
    private class QueryStatementVisitor : TSqlFragmentVisitor
    {
        public bool HasValidQuery { get; private set; }
        
        public override void Visit(SelectStatement node) => HasValidQuery = true;
        public override void Visit(InsertStatement node) => HasValidQuery = true;
        public override void Visit(UpdateStatement node) => HasValidQuery = true;
        public override void Visit(DeleteStatement node) => HasValidQuery = true;
        public override void Visit(MergeStatement node) => HasValidQuery = true;
        // 可根据业务需求添加其他需要验证的语句类型,如ExecuteStatement、CreateTableStatement等
    }
}

二、其他可选的SQL验证方案

如果不想基于TSqlParser扩展,也可以考虑以下库:

  • Dapper.SqlParser:轻量型SQL解析库,专注于查询语句的合法性校验,对随机字符串这类无效输入的识别更严格
  • ANTLR4 TSQL语法库:基于ANTLR4生成的TSQL语法解析器,可通过自定义语法规则精准过滤无效的孤立标识符

关键说明

TSqlParser的设计目标是解析合法的TSQL批处理语句,而非专门验证“完整可执行的查询语句”,所以孤立标识符会被视为合法批处理(比如单独的变量名@var或存储过程名sp_help)。通过自定义语法树访问器,可以精准控制需要验证的SQL语句类型,彻底避免随机字符串的误判问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:15:25