2011-04-26 7 views
11

Básicamente, estoy buscando un equivalente a SqlCommandBuilder.DeriveParameters que funcione para T-SQL arbitrario.¿Cómo puedo determinar los parámetros requeridos por una pieza arbitraria de T-SQL?

Por ejemplo, esta consulta requiere un parámetro:

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

Básicamente necesito para extraer:

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

desde arriba. Podría construir un analizador SQL, pero tengo una conexión abierta al servidor SQL, así que preferiría usar una opción existente si es posible.


Editar:

Hay tiene que haber una manera de hacer esto, porque Business Intelligence Development Studio de SQL Server es capaz de hacer esto con mucho éxito.


Edición 2:

OFERTAS SQL está ejecutando este comando con el fin de describir los resultados:

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 

que explica cómo se puede determinar las columnas, pero puede ser solo cadena de análisis para obtener los parámetros ...

+0

¿Cómo estás construyendo esta cadena inicial? ¿Hay algo que pueda usar que esté usando para construir dinámicamente esta cadena para encontrar los parámetros requeridos? – mservidio

+0

¿El Analizador de SQL muestra algo interesante si mira el servidor mientras obtiene Business Intelligence Development Studio para hacerlo? Nos diría si se trata de una función de servidor o simplemente un análisis de cadenas – AakashM

+0

Quizás solo utilice una expresión regular para encontrar las @variables que no están entre comillas ... eso debería funcionar, creo. – mservidio

Respuesta

10

Puede usar Microsoft.Data.Schema.ScriptDom para esto. No estoy familiarizado con esto, pero intenté analizar su extracto y pude ver que las variables estaban accesibles en la colección ScriptTokenStream (no estoy seguro si hay una manera más fácil de obtenerlas o no)

Editar: ¡Publicando el código de OP de los comentarios!

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 también introduce sp_describe_undeclared_parameters que es de relevancia, pero falla con este ejemplo, ya que tiene que ser capaz de deducir los tipos de datos.

+0

¿Cómo puedo usar esto para obtener las tablas en una consulta SQL? Intenté reemplazar Variable con Table en tu código. No funciona. Cuando uso el identificador, me da nombres de columnas y nombres de tablas. ¿Hay alguna forma de obtener solo los nombres de las tablas? –

+0

@DeepanCool La respuesta de Gert Draper aquí parece que va a hacer eso https://social.msdn.microsoft.com/Forums/sqlserver/en-US/24fd8fa5-b1af-44e0-89a2-a278bbf11ae0/parsing?forum=ssdt –

1

Use RegEx y analice los parámetros, lo probé rápidamente , por lo que no estoy seguro de si funcionará, podría necesitar una modificación.

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

Si necesita modificar la cadena de expresión regular, encuentro este sitio muy útil: 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

creo SqlCommandBuilder.DeriveParameters obras preguntando a SQL Server cuáles son los parámetros, que no es una opción en este caso. Algún tipo de procesamiento de cadenas como un RegEx es probablemente la mejor opción.

Esta expresión regular podría ser capaz de hacerlo

@([_a-zA-Z]+) 

no lo he probado a mí mismo, pero su similar question de esta

También encontrará parámetros en los comentarios y cadenas entre comillas, pero es un comienzo.

Cuestiones relacionadas