【问题标题】:How can I determine the parameters required by an arbitrary piece of T-SQL?如何确定任意一段 T-SQL 所需的参数?
【发布时间】:2011-08-13 03:29:54
【问题描述】:

基本上,我正在寻找可用于任意 T-SQL 的 SqlCommandBuilder.DeriveParameters 等效项。

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

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

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

【问题讨论】:

  • 你是如何构建这个初始字符串的?有什么可以用来动态构建此字符串以查找所需参数的东西吗?
  • 如果您在让 Business Intelligence Development Studio 执行此操作的同时观察服务器,SQL Profiler 是否会显示任何有趣的东西?会告诉我们它是一个服务器函数还是只是字符串解析
  • @Martin;我的天啊!我认为这就是我需要的。请将其发布为答案。
  • @Martin:发布此代码:` var sql = "SELECT @Foo [Foo], '@Bar' [Bar], @Baz [Baz]"; var p = new TSql100Parser(true); var errors = new List(); 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(); }`

标签: c# .net tsql reflection


【解决方案1】:

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

编辑:从 cmets 发布 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,这与此示例相关但失败了,因为它需要能够推断数据类型。

【讨论】:

  • 如何使用它来获取 SQL 查询中的表。我尝试在您的代码中用表替换变量。它不工作。当我使用标识符时,它同时给出了列名和表名。有没有办法只获取表名?
  • @DeepanCool Gert Draper 在这里的回答看起来会做到这一点social.msdn.microsoft.com/Forums/sqlserver/en-US/…
【解决方案2】:

使用正则表达式并解析参数,我很快测试了这个,所以不确定是否有效,可能需要修改。

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

如果你需要修改正则表达式字符串,我觉得这个网站很有帮助: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();
        }
    }

【讨论】:

    【解决方案3】:

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

    这个正则表达式也许可以做到

    @([_a-zA-Z]+) 
    

    自己没试过,不过来自similar question

    它还会在 cmets 和带引号的字符串中找到参数,但这是一个开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-02
      • 2012-05-09
      • 2011-06-01
      • 2013-02-18
      • 2018-09-13
      • 2014-08-02
      • 2011-03-25
      • 1970-01-01
      相关资源
      最近更新 更多