2011-07-29 22 views
6

Digamos que tengo una consulta como esta:¿Hay alguna manera de especificar el nombre de la tabla como una cadena?

SELECT * FROM 
(
    SELECT * FROM 
    (
    SELECT * FROM DB.dbo.Table 
) 
    INNER JOIN DB.dbo.Table ON ... 

Me postulo esta consulta varias veces con diferentes mesas cambiando manualmente la cadena en todas partes. He intentado declarar lo siguiente:

DECLARE @tablename AS VARCHAR(255) 
SET @tablename = 'DB.dbo.Table' 

pero esto no parece funcionar, ya que me tira un error diciendo que necesito para declarar @tablename como una variable de tabla antes de poder utilizarlo. ¿Cómo planeo mi nombre de tabla y si eso es posible, seguirá funcionando Intellisense?

Respuesta

7

se puede envolver en una instrucción EXEC así:

declare @my_tablename nvarchar(100) = 'mytable'; 
exec(' 
SELECT * FROM 
(
    SELECT * FROM 
    (
    SELECT * FROM ' + @my_tablename + ' 
) 
    INNER JOIN ' + @my_tablename + ' ON ...' 
); 

Pero no, IntelliSense no va a funcionar en ese escenario.

Si sabe cuál será su salida de antemano, puede declarar una tabla temporal para contener los resultados, y luego puede acceder a eso sin EXEC. Tendrás intellisense en la mesa temporal.

Por ejemplo:

--this must match whatever your SELECT is going to return 
    CREATE TABLE #results(
    FIELD1 INT 
    ,FIELD2 NVARCHAR(100) 
    ,FIELD3 BIT 
    ); 

EXEC(' 
    INSERT INTO #results(field1,field2,field3) 
    SELECT FIELD1,FIELD2,FIELD3 FROM ' + @my_tablename 
); 

select * from #results --you will have intellisense on #results 
3

utiliza SQL dinámico. No estoy seguro de por qué necesita tantas SELECTs anidados pero sería algo así como:

DECLARE @sql NVARCHAR(MAX) = N'SELECT ... FROM ' + @tablename + '...'; 
EXEC sp_executeSQL @sql; 

Sin embargo Tenga en cuenta de la inyección de SQL. Y no, IntelliSense no tiene la capacidad de analizar una cadena de nombres de objeto (o incluso saber al editar qué nombre de objeto va a estar allí).

+0

+1. Gracias por mencionar la inyección de dependencia. –

4

No. Así como no puede especificar el nombre de la función en su programa C# como una cadena. Se supone que la compilación de T-SQL debe presentar un plan de acceso preciso, es decir, qué índices abrir y utilizar para satisfacer la consulta. Sería imposible elaborar un plan para una 'cadena', del mismo modo que sería imposible en C# generar el código para invocar una 'cadena' como método.

La solución es SQL dinámico:

declare @sql NVARCHAR(MAX) = N'SELECT ... FROM ' + 
    quotename(@dbname) + N'.' + quotename(@schema) + N'.' + quotename(@table) + 
    N' WHERE ...'; 
exec sp_executesql @sql; 

... al igual que en C# que usaría la reflexión para hacer la invocación dinámica en tiempo de ejecución.

Para más información, vea The Curse and Blessings of Dynamic SQL.

PS. la división de @tablename en componentes y el uso de QUOTENAME es una necesidad absoluta, protege contra la inyección de SQL. Use PARSENAME para hacer la división por usted.

+0

+1 para el enlace, siempre es el primer lugar a donde ir cuando se trata de SQL dinámico – Lamak

Cuestiones relacionadas