如何用Microsoft ScriptDom提取MERGE语句中的表名与别名
解决MERGE语句解析时目标表别名提取为null的问题
使用Microsoft.SqlServer.TransactSql.ScriptDom解析MERGE语句时,需要提取所有涉及的表名及其别名并存入字典。例如以下SQL:
MERGE INTO t_dpatch_parent a USING t_dpatch_child b ON (a.student_id = b.student_id) WHEN MATCHED THEN UPDATE SET a.Proposed_Fee = b.collage_fee
期望得到字典:{ "t_dpatch_parent": "a", "t_dpatch_child": "b" },但原代码中t_dpatch_parent的别名返回null,无法得到正确结果。
原代码如下:
class TableAliasVisitor : TSqlFragmentVisitor { private readonly Dictionary<string, string> _tableAliases = new Dictionary<string, string>(); public Dictionary<string, string> TableAliases { get { return _tableAliases; } } public override void Visit(NamedTableReference node) { string tableName = node.SchemaObject.BaseIdentifier.Value; string tableAlias = node.Alias?.Value; _tableAliases[tableName] = tableAlias; base.Visit(node); } }
问题原因
MERGE语句中,MERGE INTO后的目标表对应的是MergeTarget类型,而非NamedTableReference。原Visitor只重写了Visit(NamedTableReference)方法,只能捕获USING子句里的表,漏掉了目标表的别名解析。
解决方案
重写Visit(MergeTarget)方法,单独处理MERGE的目标表,提取其表名和别名:
class TableAliasVisitor : TSqlFragmentVisitor { private readonly Dictionary<string, string> _tableAliases = new Dictionary<string, string>(); public Dictionary<string, string> TableAliases => _tableAliases; // 处理MERGE的目标表(MERGE INTO后面的表) public override void Visit(MergeTarget node) { if (node.TableReference is NamedTableReference namedTable) { string tableName = namedTable.SchemaObject.BaseIdentifier.Value; string tableAlias = node.Alias?.Value; _tableAliases[tableName] = tableAlias; } base.Visit(node); } // 处理USING子句里的表 public override void Visit(NamedTableReference node) { // 避免重复处理(因为MergeTarget里的NamedTableReference会触发此方法) string tableName = node.SchemaObject.BaseIdentifier.Value; if (!_tableAliases.ContainsKey(tableName)) { string tableAlias = node.Alias?.Value; _tableAliases[tableName] = tableAlias; } base.Visit(node); } }
说明
Visit(MergeTarget)方法中,从node.TableReference获取目标表的NamedTableReference实例以提取表名;目标表的别名直接从node.Alias获取,这是它和USING子句表别名的不同之处。- 在
Visit(NamedTableReference)中增加存在性判断,避免因为MergeTarget里的NamedTableReference触发此方法导致重复添加表项。
修改后即可正确获取MERGE语句中两个表的名称和别名。
内容的提问来源于stack exchange,提问作者Varun Rajput
相关产品推荐
相关产品推荐

