È "legale" CREARE e GOCCIARE #SomeTable più di una volta?


8

Ho il mio codice un po 'segregato come "blocchi coerenti" che posso inserire più volte in uno "script di configurazione" più lungo, e uno dei modelli che sto usando è questo:

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

Ma ora SSMS si lamenta che l'oggetto esiste già la prossima volta che gli CREATE TABLEincendi. Cosa dà?

Penso che sia ovvio che dovrò dichiarare la tabella una volta all'inizio dello script, troncare invece di rilasciarla, ma è frustrante, naturalmente, non poter semplicemente abbandonare la tabella e usare di nuovo lo stesso nome.


Come ha commentato Aaron di seguito, se questa è la strada che hai seguito, la soluzione più semplice sarebbe probabilmente quella di eliminare #TABLE alla fine dello script e semplicemente TRUNCARLO nei passaggi tra. Ciò presuppone che non sia possibile ridisegnare la sceneggiatura in modo che funzioni diversamente in primo luogo. :)
Kahn,

1
Questo è quello che ho fatto per risolverlo. Ero solo confuso dal comportamento. Ha spiegato il motivo per cui è quello che volevo di più e come risolverlo.
jcolebrand

Risposte:


11

No, il parser non ti permetterà di creare la stessa tabella #temp due volte nello stesso batch (e questo non ha nulla a che fare con SSMS). Non importa nemmeno se una sola copia della tabella #temp potesse mai essere creata; ad esempio, nella seguente logica condizionale, che per gli umani potrebbe ovviamente eseguire solo un ramo, SQL Server non può vederlo:

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

Messaggio 2714, livello 16, stato 1, riga 8
È già presente un oggetto denominato "#x" nel database.

E per dimostrare che SSMS non si lamenta al momento della compilazione (un malinteso comune):

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;

Fornisce lo stesso errore esatto, anche se SSMS non tenta di analizzare o convalidare SQL dinamico prima di inviarlo al server tramite sp_executesql.

La soluzione, ovviamente, è riutilizzare la stessa tabella #temp invece di rilasciarla, utilizzare una tabella #temp diversa ogni volta o non utilizzare le tabelle #temp in primo luogo.

Questo non è qualcosa che dovresti aspettarti che SQL Server gestisca meglio. In altre parole, abituati a qualsiasi soluzione alternativa decidi.

Vedi anche questa risposta correlata su Stack Overflow che fornisce una spiegazione alternativa:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.