Подтвердить что ты не робот

Как определить параметры, необходимые для произвольного фрагмента T-SQL?

В принципе, я ищу эквивалент SqlCommandBuilder.DeriveParameters, который будет работать для произвольного T-SQL.

Например, для этого запроса требуется один параметр:

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

Мне в основном нужно извлечь:

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

Сверху. Я мог бы создать парсер SQL, но у меня есть открытое соединение с SQL-сервером, поэтому я предпочел бы использовать существующую опцию, если это возможно.

<ч/" > Edit:

Должен быть способ сделать это, потому что SQL Server Business Intelligence Development Studio может сделать это очень успешно.

<ч/" > Изменить 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

Что объясняет, как он может определять столбцы, но это может быть просто синтаксический анализ для получения параметров...

4b9b3361

Ответ 1

Вы можете использовать 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, который имеет значение, но с этим примером не работает, поскольку он должен иметь возможность выводить типы данных.

Ответ 2

Используйте 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();
        }
    }

Ответ 3

Я думаю, что SqlCommandBuilder.DeriveParameters работает, задавая SQL Server параметры, которые не являются опцией в этом случае. Возможно, что-то вроде строковой обработки, такой как RegEx.

Это Regex может сделать это

@([_a-zA-Z]+) 

Не пробовал сам, но это из этого похожего вопроса

Он также найдет параметры в комментариях и цитируемых строках, но в начале.