2012-02-23 9 views
16

¿Alguien puede comprobar en mi estado ...SQL declarar variables

DECLARE @tblName varchar(MAX), 
     @strSQL varchar(MAX) 

SET @tblName ='SELECT DISTINCT o.name as TableName 
       FROM sysobjects o 
       JOIN sysindexes x on o.id = x.id 
       WHERE o.name LIKE ''%empty%''' 

SET @strSQL = 'INSERT INTO @tblName VALUES(''trylng'', ''1'')' 
EXEC (@strSQL) 

mi error es ...

Msg 1087, nivel 15, estado 2, línea 1
Debe declarar la variable de tabla "@tblName".

+3

Espero que haya solo dos columnas en cualquier tabla que se devuelva, y el tipo de datos coincide ... –

+0

@OMGPonies: Quiere decir columnas insertables, por supuesto. –

Respuesta

6
No

seguro exactamente lo que estamos tratando de hacer, pero creo que usted quiere algo como esto:

DECLARE @tblName varchar(MAX), @strSQL varchar(MAX) 
SET @tblName = 
    (select distinct o.name as TableName 
    from sysobjects o 
    join sysindexes x on o.id = x.id 
    where o.name LIKE '%empty%') 
SET @strSQL = 'INSERT INTO [' + @tblName + '] VALUES(''trylng'', ''1'')' 
exec (@strSQL) 

Dicho esto, todavía hay un par de cosas a tener en cuenta aquí. Debe manejar la condición en la que SELECT DISTINCT devuelve algo que no sea un solo registro. Además, realmente no entiendo la necesidad de construir SQL dinámico (en @strSQL) cuando @tblName siempre tendrá el mismo valor (ya que no hay variables utilizadas en la cláusula WHERE).

+1

+1, solo una nota: generalmente es más seguro incorporar nombres en scripts dinámicos como este: ''INSERT INTO' + QUOTENAME (@tblName) + '...'', en lugar de simplemente poner corchetes alrededor de ellos. –

+0

gracias por la información Andriy –

+0

@AndriyM: Cool, gracias por la sugerencia! – rsbarro

12

Su propiedad @tblName existe en el ámbito exterior - el alcance de sus líneas de código "normales" - pero no en el ámbito interno del SQL que está construyendo en la cadena de allí ....

Es necesario para cambiar sus líneas para que diga:

SET @strSQL = 'INSERT INTO ' + @tblName + ' VALUES(''trylng'', ''1'')' 

y luego debería funcionar bien.

Además, usted no está mencionando su versión de SQL Server - pero a partir de SQL Server 2005 o posterior, debe dejar de usar sysobjects y sysindexes - en su lugar, utilice el nuevo esquema sys que contiene más o menos la misma información - pero más fácilmente disponible. Cambiar la consulta a:

SET @tblName ='SELECT DISTINCT t.name as TableName 
       FROM sys.tables t 
       INNER JOIN sys.indexes i on i.object_id = t.object_id 
       WHERE t.name LIKE ''%empty%''' 

Ver MSDN: Querying the SQL Server System Catalog para mucha más información sobre lo que está disponible en el nuevo esquema de sys y cómo sacar el máximo provecho de ella!

Como "rsbarro" señaló: poner aquí esta declaración SQL entre comillas es impar - ¿está ejecutando esta instrucción usando EXEC(...), también? Pero entonces, ¿cómo se asigna el valor a la propiedad @tblName? Realmente no tiene sentido .....

Si desea ejecutar realmente esta consulta para obtener un valor, se debe tener algo como esto:

SELECT TOP 1 @tblName = t.name 
FROM sys.tables t 
INNER JOIN sys.indexes i on i.object_id = t.object_id 
WHERE t.name LIKE '%empty%' 

Es necesario tener un TOP 1 allí ser seguro para obtener un solo valor; de lo contrario, esta instrucción podría fallar (si se seleccionan varias filas).

+0

¿Me estoy perdiendo algo? ¿Por qué @tblName está entre comillas simples? ¿No será eso justo igual a la cadena, y no al nombre de la tabla? – rsbarro

+0

No, me refiero a la segunda declaración. ¿No debería leer 'SET @tblName = SELECT DISTINCT t.name ...' sin comillas? La forma en que está escrito @strSQL tendrá un valor de 'INSERT INTO SELECT DISTINCT t.Name as TableName ...'. Me parece que será inválido, ¿no? – rsbarro

+0

@rsbarro: ah ok - bueno, no estoy seguro - estaba asumiendo que el OP estaría ejecutando esa declaración SQL usando 'EXEC (....)' también. Si no, entonces tienes toda la razón, ¡no funcionará! –

Cuestiones relacionadas