É "legal" CRIAR e DROP #SomeTable mais de uma vez?

8

Eu tenho meu código meio que segregado como "blocos coerentes" que posso inserir em um "script de configuração" mais e mais, e um dos padrões que estou usando é o seguinte:

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

Mas agora o SSMS está reclamando que o objeto já existe na próxima vez em que o CREATE TABLEfogo for disparado. O que da?

Eu acho que é óbvio que terei que declarar a tabela uma vez no início do script, truncar em vez de soltar, mas é frustrante, naturalmente, não poder soltar a tabela e usar o mesmo nome novamente.

jcolebrand
fonte
Como Aaron comentou abaixo, se esse for o caminho que você seguiu, a solução mais fácil seria soltar o #TABLE no final do script e simplesmente TRUNCATE-O nas etapas intermediárias. Isso pressupõe que não é possível apenas reprojetar o script para funcionar de maneira diferente em primeiro lugar. :)
Kahn
11
Na verdade, foi o que fiz para resolvê-lo. Eu só estava confuso com o comportamento. Ele explicou o porquê do que eu queria mais do que como consertar.
Jcolebrand

Respostas:

11

Não, o analisador não permitirá que você crie a mesma tabela #temp duas vezes no mesmo lote (e isso não tem nada a ver com o SSMS). Não importa se apenas uma cópia da tabela #temp poderia ser criada; por exemplo, na seguinte lógica condicional, que para humanos obviamente só poderia executar uma ramificação, o SQL Server não pode ver isso:

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, Nível 16, Estado 1, Linha 8
Já existe um objeto chamado '#x' no banco de dados.

E para provar que o SSMS não está reclamando no momento da compilação (um equívoco comum):

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;

Rende exatamente o mesmo erro, mesmo que o SSMS não tente analisar ou validar o SQL dinâmico antes de enviá-lo ao servidor via sp_executesql.

A correção, é claro, é reutilizar a mesma tabela #temp em vez de soltar, usar uma tabela #temp diferente a cada vez ou não usar tabelas #temp em primeiro lugar.

Isso não é algo que você deve esperar do SQL Server para lidar melhor. Em outras palavras, acostume-se a qualquer solução alternativa que você escolher.

Consulte também esta resposta relacionada no Stack Overflow, que fornece uma explicação alternativa:

Aaron Bertrand
fonte