Est-il «légal» de CRÉER et DE SUPPRIMER #SomeTable plus d'une fois?

8

J'ai mon code en quelque sorte séparé en "blocs cohérents" que je peux insérer dans un "script de configuration" plus long, et l'un des modèles que j'utilise est le suivant:

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

Mais maintenant, SSMS se plaint que l'objet existe déjà lors des prochains CREATE TABLEincendies. Ce qui donne?

Je pense qu'il est évident que je vais devoir déclarer la table une fois au début du script, tronquer au lieu de la supprimer, mais c'est frustrant, naturellement, de ne pas pouvoir simplement supprimer la table et utiliser à nouveau le même nom.

jcolebrand
la source
Comme Aaron a commenté ci-dessous, si c'est la route que vous avez prise, la solution la plus simple serait probablement de supprimer la #TABLE à la toute fin du script et de simplement la TRONCER dans les étapes intermédiaires. Cela suppose qu'il n'est pas possible de reconcevoir le script pour qu'il fonctionne différemment en premier lieu. :)
Kahn
1
C'est en fait ce que j'ai fait pour le résoudre. J'étais juste confus par le comportement. Il a expliqué le pourquoi, c'est ce que je voulais plus que la façon de le réparer.
jcolebrand

Réponses:

11

Non, l'analyseur ne vous permettra pas de créer deux fois la même table #temp dans le même lot (et cela n'a rien à voir avec SSMS). Peu importe qu'une seule copie de la table #temp puisse être créée; par exemple, dans la logique conditionnelle suivante, qui pour les humains ne pourrait évidemment exécuter qu'une seule branche, SQL Server ne peut pas voir cela:

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

Msg 2714, niveau 16, état 1, ligne 8
Il existe déjà un objet nommé '#x' dans la base de données.

Et pour prouver que ce n'est pas SSMS qui se plaint au moment de la compilation (une idée fausse courante):

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;

Donne exactement la même erreur, même si SSMS n'essaie pas d'analyser ou de valider le SQL dynamique avant de l'envoyer au serveur via sp_executesql.

Le correctif, bien sûr, consiste à réutiliser la même table #temp au lieu de la supprimer, à utiliser une table #temp différente à chaque fois, ou à ne pas utiliser les tables #temp en premier lieu.

Ce n'est pas quelque chose que vous devriez vous attendre à ce que SQL Server gère mieux. En d'autres termes, habituez-vous à la solution de contournement que vous décidez.

Voir également cette réponse connexe sur Stack Overflow qui donne une autre explication:

Aaron Bertrand
la source