问题 如何确定任意一块T-SQL所需的参数?


基本上,我正在寻找相当于 SqlCommandBuilder.DeriveParameters 这将适用于任意T-SQL。

例如,此查询需要一个参数:

SELECT @Foo [Foo], '@Bar' [Bar], @Baz [Baz]

我基本上需要提取:

new[] { "Foo", "Baz" }

从上面。我可以构建一个SQL解析器,但是我有一个到SQL服务器的开放连接,所以如果可能的话我更愿意使用现有的选项。


编辑:

那里 具有 这是一种方法,因为SQL Server的商业智能开发工作室能够非常成功地完成这项工作。


编辑2:

SQL BIDS正在执行此命令以描述结果:

exec sp_executesql N'SET FMTONLY OFF;SET FMTONLY ON;SELECT @Foo [Foo], ''@Bar'' [Bar], @Baz [Baz]',
    N'@Foo sql_variant,@Baz sql_variant',
    @Foo=NULL,@Baz=NULL

这解释了它如何确定列,但它 可能 只是字符串解析来获取参数...


9047
2018-04-26 15:17


起源

你是如何构建这个初始字符串的?您是否可以使用某些东西来动态构建此字符串以查找所需的参数? - mservidio
如果在让Business Intelligence Development Studio执行此操作时观察服务器,SQL事件探查器是否显示有趣的内容?会告诉我们它是服务器功能还是只是字符串解析 - AakashM
你知道吗? Microsoft.Data.Schema.ScriptDom? - Martin Smith
@马丁;我的天啊!我想这就是我需要的。请将其作为答案发布。 - John Gietzen
@Martin:发布这段代码:`var sql =“SELECT @Foo [Foo],'@ Bar'[Bar],@ Baz [Baz]”; var p = new TSql100Parser(true); var errors = new List <ParseError>(); var tokens = p.GetTokenStream(new StringReader(sql),errors); if(errors.Count == 0){var variables =(from t in to tens,其中t.TokenType == TSqlTokenType.Variable select t.Text).ToArray(); }` - John Gietzen


答案:


您可以使用 Microsoft.Data.Schema.ScriptDom 为了这。我自己并不熟悉它,但我只是尝试解析你的语句,并且可以看到变量可以访问 ScriptTokenStream 收集(不确定是否有更简单的方法来获取它们)

编辑:从评论中发布OP自己的代码!

    var sql = "SELECT @Foo [Foo], '@Bar' [Bar], @Baz [Baz]";
    var p = new TSql100Parser(true);
    var errors = new List<ParseError>();
    var tokens = p.GetTokenStream(new StringReader(sql), errors);
    if (errors.Count == 0)
    {
        var variables = (from t in tokens where t.TokenType == 
                       TSqlTokenType.Variable select t.Text).ToArray();
    }

SQL Server 2012还介绍了 sp_describe_undeclared_parameters 这是相关的但是在这个例子中失败,因为它需要能够推导出数据类型。


10
2018-04-26 16:04



如何使用它来获取SQL查询中的表。我尝试在代码中用表替换Variable。它不起作用。当我使用Identifier时,它会同时提供列名和表名。有办法只获取表名吗? - Deepan Cool
@DeepanCool Gert Draper在这里的回答看起来会这样做 social.msdn.microsoft.com/Forums/sqlserver/en-US/... - Martin Smith


使用RegEx并解析参数,我对此进行了快速测试,因此不确定是否可行,可能需要进行修改。

[^'] @([^ [,] +)

如果您需要修改正则表达式字符串,我发现这个网站非常有用: http://regexlib.com/RETester.aspx

public Form1()
    {
        InitializeComponent();

        string query = "SELECT @Foo [Foo], '@Bar' [Bar], @Baz [Baz] ";
        Regex r = new Regex(@"[^']@([^\[,]+)");
        MatchCollection collection = r.Matches(query);
        string[] array = new string[collection.Count];

        for (int i = 0; i < collection.Count; i++)
        {
            array[i] = collection[i].Value.Trim();

            // If you want the string[] populated without the "@"
            // array[i] = collection[i].Groups[1].Value.Trim();
        }
    }

1
2018-04-26 15:35





我认为 SqlCommandBuilder.DeriveParameters 通过询问SQL Server参数是什么来工作,在这种情况下不是一个选项。像RegEx这样的字符串处理可能是你最好的选择。

这个正则表达式也许能够做到这一点

@([_a-zA-Z]+) 

没有自己试过,但它是从这个 类似的问题

它还会在注释和引用的字符串中找到参数,但它是一个开始。


0
2018-04-26 15:43