1

你好stackoverflowers,

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

这是问题的关键部分:

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());
    }

变量查询包含以下语句:

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

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

期待“点”,在第 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 的帮助!

4

1 回答 1

1

我自己也遇到了类似的问题。尝试更多类似的东西。但请注意,您提供的查询没有变量。此查询返回“@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();
        }
    }
于 2017-08-10T17:05:44.443 回答