使用 TSql120Parser 解析 T-SQL 时出错

Error on parsing T-SQL using TSql120Parser

你好 Whosebugers,

我在使用 Microsoft.SqlServer.TransactSql.ScriptDom 中的 TSql120Parser 解析 T-SQL 语句时遇到问题。我的目标是简单地解析 T-SQL select 语句并获取它的标记。

这是问题的本质部分:

using (var reader = new StringReader(query))
    {
        IList<ParseError> errors;
        var parser = new TSql120Parser(true);
        var fragment = parser.Parse(reader, out errors);

        parameters.AddRange(
            fragment.ScriptTokenStream
                .Where(token => token.TokenType == TSqlTokenType.Variable)
                .Select(token => token.Text)
                .ToList());
    }

变量query包含这条语句:

SELECT A.ColumnX, B.ColumnY FROM TableA AS A INNER JOIN TableB AS B ON A.Id = B.IdA

现在我总是得到以下错误 (antlr.MismatchedTokenException.TokenTypeEnum.TokenType):

expecting "Dot", found ',' at column 17

因为我猜这个语句是正确的(我测试了其他几个在 SQL-Server 中工作的语句,但没有被 TSql120Parser 解析),我不知道问题是什么。

我不是被迫使用这个解析器,但我认为这将是最简单和最可靠的解决方案。 如果能帮助我找到解决方案,我将不胜感激!

此致,索伦

编辑

在 Alex K 的帮助下。我发现它可以在干净的控制台应用程序中运行,但不能在我的 WPF 项目中运行。它使用相同的 Nuget 包和 .Net 4.6。 够奇怪的,它会解析类似

的内容
SELECT @column FROM @table

但不是

SELECT Column FROM Table

解决方案

TSql100Parser.Parse 在项目中不起作用,但 TSql100Parser.GetTokenStream 可以。我不知道原因,我无法在另一个项目中重现该错误。

感谢 Alex K. 和 Matthew Vines 的帮助!

我自己也遇到过类似的问题。尝试更多类似的东西。但请注意,您提供的查询没有变量。此查询 returns“@0”和“@1”的列表

SELECT product_id, AVG(sale_price)
FROM Sales
WHERE sale_date > @0
    AND ([sales].system_id = 450)
GROUP BY product_id
Having AVG(sale_price) > @1


public List<string> GetVariables(string sql)
    {
        List<string> parseErrors;
        List<TSqlParserToken> queryTokens = TokenizeSql(sql, out parseErrors);

        List<string> parameters = new List<string>();
        parameters.AddRange(queryTokens.Where(token => token.TokenType == TSqlTokenType.Variable)
                                        .Select(token => token.Text)
                                        .ToList());
        return parameters;
    }

    private List<TSqlParserToken> TokenizeSql(string sql, out List<string> parserErrors)
    {
        using (System.IO.TextReader tReader = new System.IO.StringReader(sql))
        {
            var parser = new TSql120Parser(true);

            IList<ParseError> errors;
            var queryTokens = parser.GetTokenStream(tReader, out errors);
            if (errors.Any())
            {
                parserErrors = errors.Select(e => $"Error: {e.Number}; Line: {e.Line}; Column: {e.Column}; Offset: {e.Offset};  Message: {e.Message};").ToList();
            }
            else
            {
                parserErrors = null;
            }
            return queryTokens.ToList();
        }
    }