¿Es "legal" CREAR y COLOCAR #SomeTable más de una vez?

8

Tengo mi tipo de código segregado como "bloques coherentes" que puedo insertar en un "script de configuración" más largo una y otra vez, y uno de los patrones que estoy usando es este:

CREATE TABLE #WidgetSetting 
(
    WidgetID bigint not null,
    Name nvarchar(100) not null,
    Value nvarchar(max) not null,
    CreateDate datetime not null
)

INSERT VALUES

MERGE TABLES

DROP TABLE #WidgetSetting

Pero ahora SSMS se queja de que el objeto ya existe para la próxima vez que se CREATE TABLEdispare. ¿Lo que da?

Creo que es obvio que tendré que declarar la tabla una vez al comienzo del script, truncar en lugar de soltar, pero es frustrante, naturalmente, no poder soltar la tabla y usar el mismo nombre nuevamente.

jcolebrand
fuente
Como Aaron comentó a continuación, si esta es la ruta que ha tomado, la solución más fácil sería soltar el #TABLE al final del script y simplemente TRUNCARLO en los pasos intermedios. Eso supone que no es posible simplemente rediseñar el script para que funcione de manera diferente en primer lugar. :)
Kahn
1
Eso es lo que hice para resolverlo. Estaba confundido por el comportamiento. Explicó el por qué, que es lo que quería más que la forma de solucionarlo.
jcolebrand

Respuestas:

11

No, el analizador no le permitirá crear la misma tabla #temp dos veces en el mismo lote (y esto no tiene nada que ver con SSMS). Ni siquiera importa si solo se puede crear una copia de la tabla #temp; por ejemplo, en la siguiente lógica condicional, que para los humanos obviamente solo podría ejecutar una rama, SQL Server no puede ver eso:

IF 1 = 1
BEGIN
  CREATE TABLE #x(i INT);
  DROP TABLE #x;
END
ELSE
BEGIN
  CREATE TABLE #x(j INT);
  DROP TABLE #x;
END

Mensaje 2714, Nivel 16, Estado 1, Línea 8
Ya existe un objeto llamado '#x' en la base de datos.

Y para demostrar que no es SSMS quejarse en tiempo de compilación (un error común):

DECLARE @sql NVARCHAR(MAX) = N'IF 1 = 1
BEGIN
  CREATE TABLE #x(i INT);
  DROP TABLE #x;
END
ELSE
BEGIN
  CREATE TABLE #x(j INT);
  DROP TABLE #x;
END';

EXEC sp_executesql @sql;

Produce exactamente el mismo error, aunque SSMS no intente analizar o validar SQL dinámico antes de enviarlo al servidor a través de sp_executesql.

La solución, por supuesto, es reutilizar la misma tabla #temp en lugar de soltar, usar una tabla #temp diferente cada vez, o no usar tablas #temp en primer lugar.

Esto no es algo que debería esperar que SQL Server maneje mejor. En otras palabras, acostúmbrate a cualquier solución que decidas.

Vea también esta respuesta relacionada en Stack Overflow que brinda una explicación alternativa:

Aaron Bertrand
fuente