2011-04-26 11 views
11

Zasadniczo szukam odpowiednika SqlCommandBuilder.DeriveParameters, które będzie działać dla dowolnego T-SQL.Jak określić parametry wymagane przez dowolny fragment T-SQL?

Na przykład, ta kwerenda wymaga jednego parametru:

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

I w zasadzie trzeba wyodrębnić:

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

z góry. Mogłem zbudować parser SQL, ale mam otwarte połączenie z serwerem SQL, więc wolałbym użyć istniejącej opcji, jeśli to możliwe.


Edit:

Nie ma być jakiś sposób, aby to zrobić, ponieważ SQL Server Business Intelligence Development Studio jest w stanie to zrobić bardzo skutecznie.


Edit 2:

BIDS SQL wykonuje polecenia w celu opisania wyniki:

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 

Co wyjaśnia, jak można określić kolumn, ale może być tylko ciąg parsowania, aby uzyskać parametry ...

+0

Jak budujesz ten początkowy ciąg? Czy jest coś, czego możesz użyć do dynamicznego budowania tego ciągu w celu znalezienia wymaganych parametrów? – mservidio

+0

Czy program SQL Profiler pokazuje coś interesującego, jeśli oglądasz serwer podczas pobierania Business Intelligence Development Studio, aby to zrobić? Powiedziałby nam, czy jest to funkcja serwera, czy tylko parsowanie ciągu znaków. – AakashM

+0

Być może wystarczy użyć wyrażenia regularnego, aby znaleźć @zmienne, które nie są zawarte w cudzysłowach ... które powinny działać, jak sądzę. – mservidio

Odpowiedz

10

Możesz użyć do tego Microsoft.Data.Schema.ScriptDom. Sam go nie znam, ale po prostu próbowałem analizować twoje oświadczenie i mogłem zobaczyć, że zmienne były dostępne w kolekcji ScriptTokenStream (nie wiem, czy jest łatwiejszy sposób ich złapania, czy nie)

Edytuj: Zamieszczanie własnego kodu OP z komentarzy!

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 wprowadza również sp_describe_undeclared_parameters co ma znaczenie, ale nie powiedzie się z tym przykładzie, jak to musi być w stanie wywnioskować typy danych.

+0

Jak można tego użyć, aby uzyskać tabele w zapytaniu SQL. Próbowałem zastąpić zmienną tabelą w twoim kodzie. To nie działa. Kiedy używam identyfikatora, podaje zarówno nazwy kolumn, jak i nazwy tabel. Czy istnieje sposób na uzyskanie tylko nazw tabel? –

+0

@DeepanCool Odpowiedź Gert Draper tutaj wygląda tak, jak to zrobi https://social.msdn.microsoft.com/Forums/sqlserver/en-US/24fd8fa5-b1af-44e0-89a2-a278bbf11ae0/parsing?forum=ssdt –

1

Użyj RegEx i przeanalizuj parametry, szybko przetestowałem to , więc nie wiem, czy zadziała, może potrzebować modyfikacji.

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

Jeśli trzeba zmodyfikować regularny ciąg wyrażenie, uważam to miejsce bardzo pomocne: 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(); 
     } 
    } 
0

myślę SqlCommandBuilder.DeriveParameters prace pytając SQL Server, jakie są parametry, co w tym przypadku nie jest opcją. Jakieś przetwarzanie ciągów jak RegEx jest prawdopodobnie najlepszym rozwiązaniem.

Regex ta może być w stanie zrobić to

@([_a-zA-Z]+) 

nie próbował go samodzielnie, ale jest z tym similar question

Będzie również znaleźć w komentarzach i parametry podane ciągi ale jego start.

Powiązane problemy