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

如何利用ScriptDom生成修改列名格式的T-SQL新脚本?

基于Microsoft.SqlServer.TransactSql.ScriptDom修改T-SQL列名格式的实现

需求说明

需要构建T-SQL解析器,生成符合特定规则的新查询:将所有用方括号包裹的列名替换为单引号包裹的形式(例如[B]替换为'B')。已有基于Microsoft.SqlServer.TransactSql.ScriptDom的C#代码用于提取列名,但不知道如何生成修改后的完整T-SQL脚本。

示例:
原SQL语句:

SELECT A,[B],C,[D],E FROM T  WHERE isnumeric(col3) = 1 Order by [Id] desc

期望转换后的结果:

SELECT A,'B',C,'D',E FROM T WHERE isnumeric(col3) = 1 Order by 'Id' desc

解决方案

通过自定义TSqlFragmentVisitor遍历抽象语法树(AST),替换目标节点后,使用TSqlScriptGenerator重新生成SQL脚本。具体步骤如下:

  1. 解析原SQL生成AST结构
  2. 遍历AST并替换指定格式的列名节点
  3. 将修改后的AST重新生成为SQL文本

完整代码实现

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.SqlServer.TransactSql.ScriptDom;

namespace TSqlTransformer
{
    public class QueryTransformer
    {
        public string Transform(string originalSql)
        {
            // 解析原SQL生成AST
            TSql100Parser parser = new TSql100Parser(false);
            using TextReader reader = new StringReader(originalSql);
            if (!parser.Parse(reader, out IList<ParseError> errors, out TSqlFragment fragment))
            {
                throw new InvalidOperationException($"SQL解析错误:{string.Join(", ", errors)}");
            }

            // 遍历AST并修改列名节点
            var transformerVisitor = new ColumnNameTransformerVisitor();
            fragment.Accept(transformerVisitor);

            // 生成修改后的SQL脚本
            TSql100ScriptGenerator generator = new TSql100ScriptGenerator();
            generator.GenerateScript(fragment, out string transformedSql);
            return transformedSql;
        }
    }

    internal class ColumnNameTransformerVisitor : TSqlConcreteFragmentVisitor
    {
        // 处理列引用表达式
        public override void Visit(ColumnReferenceExpression node)
        {
            // 仅处理单部分列引用(如[B]、Id,排除Schema.Table.Column这类多部分引用)
            if (node.MultiPartIdentifier.Identifiers.Count == 1)
            {
                var identifier = node.MultiPartIdentifier.Identifiers[0];
                // 替换带方括号的标识符为单引号包裹的字符串
                if (identifier is QuotedIdentifier quotedId)
                {
                    var stringLiteral = new StringLiteral
                    {
                        Value = quotedId.Value,
                        QuoteType = QuoteType.SingleQuote
                    };
                    node.MultiPartIdentifier.Identifiers[0] = stringLiteral;
                }
            }

            base.Visit(node);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string originalSql = "SELECT A,[B],C,[D],E FROM T  WHERE isnumeric(col3) = 1 Order by [Id] desc";
            QueryTransformer transformer = new QueryTransformer();
            string transformedSql = transformer.Transform(originalSql);
            Console.WriteLine("转换后的SQL:");
            Console.WriteLine(transformedSql);
        }
    }
}

代码说明

  • SQL解析:使用TSql100Parser将原SQL字符串转换为可操作的AST结构
  • 节点替换:自定义访问器遍历列引用节点,将带方括号的QuotedIdentifier替换为单引号包裹的StringLiteral
  • 脚本生成:通过TSql100ScriptGenerator将修改后的AST重新转换为标准SQL文本

扩展说明

  • 如果需要替换所有列名(包括不带方括号的),可移除对QuotedIdentifier的类型判断,直接将Identifier转换为StringLiteral
  • 若要支持多部分列引用(如dbo.Table.[Column]),可扩展Visit方法中的逻辑,判断并替换指定层级的标识符

内容的提问来源于stack exchange,提问作者adam.g

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:50:21