2009-03-27 25 views
6

Considere el siguiente código:TSQL escritura en una tabla temporal de SQL dinámico

SET @SQL1 = 'SELECT * INTO #temp WHERE ...' 
exec(@SQL1) 
SELECT * from #temp (this line throws an error that #temp doesn't exist) 

Aparentemente esto es debido a que el comando exec escinde una sesión separada y #temp es local en esa sesión. Puedo usar una tabla temporal global ## temp, pero luego tengo que idear un esquema de nombres para evitar colisiones. ¿Qué recomiendan todos?

Respuesta

1

No encontré una solución factible que hiciera todo lo que necesitaba, así que cambié a usar ## tablas temporales globales.

+10

Puede causar problemas en el entorno multiusuario – Madhivanan

+0

@Madhivanan ¿Qué problemas? – gotqn

5

¿Intenté crear una tabla de plantillas explícitamente?

Create Table #temp (..) 
+4

que no soluciona el problema de alcance. Sin embargo, dado que no conozco el esquema hasta que se ejecuta la declaración ejecutiva. (¿A menos que haya una forma de crear una tabla sin definir un esquema?) – Jeff

+0

# le indica que está utilizando tempdb, y se resuelve automáticamente en una tabla real en tempdb con un gran nombre aleatorio antiguo, lo que previene conflictos. No necesita el nombre de esquema para emitir la instrucción create, pero debe hacerlo fuera de SQL dinámico. –

2

Puede crear temp antes que exec y usar exec para rellenar la tabla temporal.

+2

¿Cómo creo la tabla temporal sin conocer el esquema? (Mi selección en define el esquema) – Jeff

1

Alternativley, puede usar una variable de tabla.

Aquí hay una buena article para discutir esto.

+1

Esto no soluciona el problema, no se puede 'SELECCIONAR ... EN' una variable de tabla y si el OP tiene un esquema de tabla estático conocido por delante, podrían usar un ' CREATE TABLE # temp' declaración. La sugerencia de variable de tabla no proporciona ninguna funcionalidad adicional. –

0

¿No puede poner su seleccionar después de la inserción con un; Delimeter y ejecutar las dos declaraciones juntas?

5

Pruebe ## temp Porque su consulta dinámica se ejecuta en otra fibra por lo que no puede ver su tabla de temporay local. en su lugar, si declaras tu tabla temporal como global, tiene sentido.

1

Un ejemplo, un vistazo a "en"

SELECT o.OrderID, o.OrderDate, od.UnitPrice, od.Quantity, 
     c.CustomerID, c.CompanyName, c.Address, c.City, c.Region, 
     c.PostalCode, c.Country, c.Phone, p.ProductID, 
     p.ProductName, p.UnitsInStock, p.UnitsOnOrder 
INTO #temp 
FROM Orders o 
JOIN [Order Details] od ON o.OrderID = od.OrderID 
JOIN Customers c ON o.CustomerID = c.CustomerID 
JOIN Products p ON p.ProductID = od.ProductID 
0

Otro método es utilizar todo el código dentro del SQL dinámico

SET @SQL1 = 'SELECT * INTO #temp WHERE ... 
SELECT * from #temp ' 
exec(@SQL1) 
0

Hay un método de crear ficticia mesa temporal con un solo columna de identidad, luego modificando esa tabla con el esquema deseado a través de SQL dinámico y llenándolo. De esta manera se puede utilizar tanto en tabla temporal dinámica y regular de SQL, se unen con él ...

-- Create dummy table 
CREATE TABLE #tmpContactData (PK int NOT NULL IDENTITY(1,1)) 

-- Alter its schema 
DECLARE @sqlCommand nvarchar(max) 
SELECT @sqlCommand = ' 
ALTER TABLE #tmpContactData 
ADD 
    EmployeeId int, 
    Address varchar(100), 
    Phone varchar(50) 
' 
EXECUTE(@sqlCommand) 

-- Fill it 
SELECT @sqlCommand = ' 
INSERT INTO #tmpContactData 
SELECT t.EmployeeId, t.Address, t.Phone 
FROM ( SELECT EmployeeId=1000, Address=''Address 1000'', Phone=''Phone 1000'' 
     UNION 
     SELECT 1001, ''Address 1001'', ''Phone 1001'' 
     UNION 
     SELECT 1002, ''Address 1002'', ''Phone 1002'' 
) t 
' 
EXECUTE(@sqlCommand) 

--select from it 
SELECT * FROM #tmpContactData 

--CleanUp 
DROP TABLE #tmpContactData 
Cuestiones relacionadas