You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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);
    }
}

说明

  1. Visit(MergeTarget)方法中,从node.TableReference获取目标表的NamedTableReference实例以提取表名;目标表的别名直接从node.Alias获取,这是它和USING子句表别名的不同之处。
  2. 在Visit(NamedTableReference)中增加存在性判断,避免因为MergeTarget里的NamedTableReference触发此方法导致重复添加表项。

修改后即可正确获取MERGE语句中两个表的名称和别名。

内容的提问来源于stack exchange,提问作者Varun Rajput

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:26:21