在 C# 中解析 SQL 代码 [关闭]

Posted

技术标签:

【中文标题】在 C# 中解析 SQL 代码 [关闭]【英文标题】:Parsing SQL code in C# [closed] 【发布时间】:2010-10-09 23:59:57 【问题描述】:

我想用 C# 解析 SQL 代码。

具体来说,是否有任何免费可用的解析器可以解析 SQL 代码并从中生成树或任何其他结构?它还应该为嵌套结构生成正确的树。

它还应该返回这棵树的节点代表哪种语句。

例如,如果节点包含一个循环条件,那么它应该返回这是一个节点的“循环类型”。

或者有什么方法可以解析 C# 中的代码并生成我想要的类型的树?

【问题讨论】:

***.com/questions/34102835 【参考方案1】:

特别是对于 Transact-SQL (Microsoft SQL Server),您可以使用 Microsoft.SqlServer.Management.SqlParser.dll 中提供的the Microsoft.SqlServer.Management.SqlParser.Parser namespace,这是 SQL Server 附带的一个程序集,可以免费分发.

这是一个将 T-SQL 作为字符串解析为标记序列的示例方法:

IEnumerable<TokenInfo> ParseSql(string sql)

    ParseOptions parseOptions = new ParseOptions();
    Scanner scanner = new Scanner(parseOptions);

    int state = 0,
        start,
        end,
        lastTokenEnd = -1,
        token;

    bool isPairMatch, isExecAutoParamHelp;

    List<TokenInfo> tokens = new List<TokenInfo>();

    scanner.SetSource(sql, 0);

    while ((token = scanner.GetNext(ref state, out start, out end, out isPairMatch, out isExecAutoParamHelp)) != (int)Tokens.EOF)
    
        TokenInfo tokenInfo =
            new TokenInfo()
            
                Start = start,
                End = end,
                IsPairMatch = isPairMatch,
                IsExecAutoParamHelp = isExecAutoParamHelp,
                Sql = sql.Substring(start, end - start + 1),
                Token = (Tokens)token,
            ;

        tokens.Add(tokenInfo);

        lastTokenEnd = end;
    

    return tokens;

请注意,TokenInfo 类只是一个具有上述属性的简单类。

Tokens是这个枚举:

Tokens Enumeration (Microsoft.SqlServer.Management.SqlParser.Parser)

并包括TOKEN_BEGINTOKEN_COMMITTOKEN_EXISTS 等常量。

【讨论】:

它看起来是最好的。但我似乎必须手动构建一个表达式树。【参考方案2】:

Scott Hanselman 最近featuredIrony project 包含一个示例 SQL 解析器。

【讨论】:

(由于 CodePlex 正在关闭,有更新链接:github.com/IronyProject/Irony)【参考方案3】:

[警告:自 2021 年起,答案可能不再适用]

使用 Microsoft Entity Framework (EF)。

它有一个构建表达式树的“Entity SQL”解析器,

using System.Data.EntityClient;
...
EntityConnection conn = new EntityConnection(myContext.Connection.ConnectionString);
conn.Open();
EntityCommand cmd = conn.CreateCommand();
cmd.CommandText = @"Select t.MyValue From MyEntities.MyTable As t";
var queryExpression = cmd.Expression;
....
conn.Close();

或者类似的,在 MSDN 上查看。

这一切都在鲍尔默打勾:-)

代码项目中也有一个,SQL Parser

祝你好运。

【讨论】:

这需要“Entity-SQL”,一种SQL的方言;我相信 OP 意味着常规 SQL,例如“Transact-SQL”(SQL Server 的方言)。简而言之;这行不通。 据我所知,无论哪种方式,都没有关于原始问题的线索?所以在我们解决这个问题之前,我们应该等待@aaCog 确认吗? 我在 msdn 上找不到 EntityCommand 的 Expression 属性。 msdn.microsoft.com/en-us/library/… 对于 -ve 'ers。这个答案在 2009 年有效。EF 已经继续前进,这不再适用 @TFD - 然而,这个答案不再正确的事实是拒绝投票的正当理由。如您所知,这就是 *** 的工作方式。它依赖于人们更新答案,或者接受它将被否决,以优先选择更正确的答案来投票。【参考方案4】:

你可以看看一个商业组件:general sql parser at http://www.sqlparser.com 支持Oracle、T-SQL、DB2和mysql的SQL语法。

【讨论】:

在 xml 输出中生成内部查询分析树以供进一步处理。支持嵌套子查询、复杂连接和存储过程中的语句。 dpriver.com/blog/… 是的,我正在使用它,API 有点令人困惑,但绝对可以完成工作。价格也很合理。支持非常有帮助。【参考方案5】:

试试ANTLR - 上面有一堆 SQL 语法。

【讨论】:

.NET 中的任何示例应用程序——如果可能的话,带有源代码——使用 AntLR ?? @PuterdoBorato 链接似乎已失效 :( @Chris 我能够使用 Antler 4.5.3 和 .不过,这似乎是不可编译的。已编译的解析器:github.com/another-guy/SqlSchemer/tree/… 您可以按照自己的步骤编译 SQL 解析器(也许您有更多的运气解决问题):github.com/another-guy/SqlSchemer/issues/2 如果您这样做了,请告诉我。我仍然需要一个有效的解析器......【参考方案6】:

VSTS 2008 数据库版 GDR 包括处理 SQL 解析和脚本生成的程序集,您可以从项目中引用这些程序集。 Database Edition 使用解析器解析脚本文件以表示数据库的内存模型,然后使用脚本生成器从模型生成 SQL 脚本。我认为您的项目中只需要拥有和引用两个程序集。如果您没有数据库版本,您可以安装试用版来获取程序集,或者可能有另一种方法来获得它们而无需安装数据库版本。查看以下链接。 Data Dude:Getting to the Crown Jewels .

【讨论】:

Mehmet,VSTS 2008 数据库版 GDR 管理 Oracle 的 Sql 解析??【参考方案7】:

试试GOLD Parser,它是一个功能强大且易于学习的 BNF 引擎。您可以搜索已经创建的语法以获得所需的内容(即:SQL ANSI 89 Grammar)。

我开始将它用于 HQL 解析(NHibernate 查询语言,与 SQL 非常相似),它非常棒。

更新:现在 NH 开发团队已经使用 ANTLR(更难使用,但更强大的 AFAIK)完成了 HQL 解析。

【讨论】:

【参考方案8】:

正如 Diego 所建议的,语法是 IMHO 的必经之路。我之前尝试过 Coco/r,但这对于复杂的 SQL 来说太简单了。 ANTLR 和 a number of grammars 准备好了。

有人甚至尝试构建 SQL 引擎,请检查代码是否有适合您的内容 SharpHSQL - An SQL engine written in C#

【讨论】:

以上是关于在 C# 中解析 SQL 代码 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中解析 html 的最佳方法是啥? [关闭]

c# 怎样能写个sql的解析器

如何用 C# 编写解析器? [关闭]

如何在 C# 中解析复杂的 JSON?最终我想在 DataGridView 中显示结果 [关闭]

使用 C# 从文件中解析 JSON 数据 [关闭]

JSON解析数组C# [关闭]