使用 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();
}
}
你好 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();
}
}