Является ли «законным» создание и удаление #SomeTable более одного раза?

8

У меня есть своего рода код, выделенный как «связные блоки», которые я могу снова и снова вставлять в более длинный «скрипт конфигурации», и один из шаблонов, которые я использую, таков:

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

Но теперь SSMS жалуется, что объект уже существует к следующему CREATE TABLEпожару. Что дает?

Я думаю, что очевидно, что мне придется объявить таблицу один раз в начале скрипта, усечь вместо удаления, но, естественно, разочаровывает невозможность просто удалить таблицу и снова использовать то же имя.

Jcolebrand
источник
Как прокомментировал Аарон ниже, если вы выбрали именно этот маршрут, то самым простым решением было бы удалить #TABLE в самом конце скрипта и просто TRUNCATE его между шагами. Это предполагает, что невозможно просто изменить дизайн скрипта, чтобы он работал по-другому. :)
Кан
1
Это на самом деле то, что я сделал, чтобы решить это. Я был просто смущен поведением. Он объяснил, почему именно то, что я хотел больше, чем то, как это исправить.
Jcolebrand

Ответы:

11

Нет, парсер не позволит вам создать одну и ту же таблицу #temp дважды в одном пакете (и это не имеет никакого отношения к SSMS). Даже не имеет значения, можно ли создать только одну копию таблицы #temp; например, в следующей условной логике, которая для людей, очевидно, могла когда-либо выполнять только одну ветку, SQL Server не может этого увидеть:

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

Сообщение 2714, уровень 16, состояние 1, строка 8
В базе данных уже есть объект с именем '#x'.

И чтобы доказать, что SSMS не жалуется во время компиляции (распространенное заблуждение):

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;

Выдает точно такую ​​же ошибку, даже если SSMS не пытается анализировать или проверять динамический SQL перед отправкой его на сервер через sp_executesql.

Исправление, конечно, состоит в том, чтобы повторно использовать одну и ту же таблицу #temp вместо удаления, каждый раз использовать другую таблицу #temp или не использовать таблицы #temp в первую очередь.

Это не то, что вы должны ожидать от SQL Server для лучшей обработки. Другими словами, привыкните к любому обходному решению, с которым вы решите.

Смотрите также этот связанный ответ о переполнении стека, который дает альтернативное объяснение:

Аарон Бертран
источник