如何用C# ScriptDom提取SQL Server查询中的关联表及关联列?
可以用C# ScriptDom实现SQL关联列提取需求
完全可以通过ScriptDom实现这个需求。ScriptDom是微软官方提供的TSQL语法解析库,能将SQL语句解析为结构化的抽象语法树(AST),我们只需要遍历AST中的JOIN条件节点,提取其中的表名和关联列即可。
实现步骤
- 引入依赖:先安装
Microsoft.SqlServer.TransactSql.ScriptDomNuGet包,这是解析TSQL的核心库。 - 自定义AST访问器:继承
TSqlConcreteFragmentVisitor,重写Visit(BinaryExpression node)方法,专门处理JOIN ON子句中的等值判断(BinaryExpressionType.Equals类型的节点)。 - 提取列信息:在访问器中,识别等值表达式两侧的
ColumnReferenceExpression节点,从中解析出表别名/表名和列名。 - 解析SQL并收集结果:用
TSql160Parser解析目标SQL,再用自定义访问器遍历AST,收集所有关联列信息。
示例代码
using Microsoft.SqlServer.TransactSql.ScriptDom; using System; using System.Collections.Generic; using System.IO; using System.Linq; public class JoinColumnVisitor : TSqlConcreteFragmentVisitor { public List<(string TableName, string ColumnName)> JoinColumns { get; } = new(); public override void Visit(BinaryExpression node) { // 仅处理等值关联的场景 if (node.BinaryExpressionType == BinaryExpressionType.Equals) { ExtractColumnInfo(node.FirstExpression); ExtractColumnInfo(node.SecondExpression); } base.Visit(node); } private void ExtractColumnInfo(TSqlFragment expression) { if (expression is ColumnReferenceExpression columnRef) { // 提取表名和列名(适配[表名].[列名]格式的引用) if (columnRef.MultiPartIdentifier.Identifiers.Count >= 2) { string tableName = columnRef.MultiPartIdentifier.Identifiers[0].Value; string columnName = columnRef.MultiPartIdentifier.Identifiers[1].Value; JoinColumns.Add((tableName, columnName)); } } } } public class SqlAnalyzer { public static List<(string TableName, string ColumnName)> ExtractJoinColumns(string sql) { var parser = new TSql160Parser(false); IList<ParseError> errors; using var reader = new StringReader(sql); var fragment = parser.Parse(reader, out errors); if (errors.Count > 0) { throw new InvalidOperationException($"SQL解析错误:{string.Join(", ", errors.Select(e => e.Message))}"); } var visitor = new JoinColumnVisitor(); fragment.Accept(visitor); // 可选:对结果去重,避免重复输出同一表列 return visitor.JoinColumns.Distinct().ToList(); } } // 测试示例 class Program { static void Main() { string sql = @"SELECT * FROM tabel1 INNER JOIN tabel2 ON tabel1.varchar1col = tabel2.varchar1col INNER JOIN tabel3 ON tabel1.varchar2col = tabel3.varchar2col LEFT JOIN tabel4 ON tabel3.varchar2col = tabel4.varchar3col"; var joinColumns = SqlAnalyzer.ExtractJoinColumns(sql); foreach (var (table, column) in joinColumns) { Console.WriteLine($"{table} {column}"); } } }
输出结果
运行上述代码后,会输出和你期望完全一致的内容:
tabel1 varchar1col tabel2 varchar1col tabel1 varchar2col tabel3 varchar2col tabel4 varchar3col
内容的提问来源于stack exchange,提问作者adam.g
相关产品推荐
相关产品推荐

