Reunindo um processo rápido para ajudar na depuração, encontrei um que parece ser um erro no compilador.
create proc spFoo
@param bit
as
begin
if @param = 0
begin
select *
into #bar
from [master].dbo.spt_values
-- where number between ...
end
else
begin
select top 10 *
into #bar
from [master].dbo.spt_values
order by newid();
end;
end;
Tentativa acima, retorna o seguinte erro
Msg 2714, Nível 16, Estado 1, Procedimento spFoo, Linha 19
Já existe um objeto chamado '#bar' no banco de dados.
Em um sentido legível por humanos, o proc parece estar bem: apenas uma select into
declaração será executada, uma vez que estão dentro dos if-else
blocos. Muito bem, o SQL Server não pode confirmar se as instruções são logicamente excluídas uma da outra. Talvez o mais confuso seja o fato de que o erro permanece quando drop table #foo
é colocado dentro do bloco if-else (que se supõe que seria dito ao compilador para desalocar o nome do objeto) como abaixo.
create proc spFoo
@param bit
as
begin
select top 1 *
into #bar
from [master].dbo.spt_values
if @param = 0
begin
drop table #bar;
select *
into #bar
from [master].dbo.spt_values
-- where number between ...
end
else
begin
drop table #bar;
select top 10 *
into #bar
from [master].dbo.spt_values
order by newid();
end;
end;
O proc em si está bem. Eu peguei e escrevi as declarações create table #foo( ... )
e insert #foo ( ... )
, eu estava tentando pular com a select * into
sintaxe. Neste ponto, estou apenas tentando entender por que o compilador me cagou com a sintaxe do cara preguiçoso. A única coisa em que consigo pensar é que o comando DDL reserva o nome do objeto IN TEMPDB .
Por que o texto em negrito?
create proc spIck
as
begin
create table #ack ( col1 int );
drop table #ack;
create table #ack ( colA char( 1 ) );
drop table #ack;
end;
Isso falha com o mesmo código de erro acima. Mas o seguinte ...
create proc spIck
as
begin
create table ack ( col1 int );
drop table ack;
create table ack ( colA char( 1 ) );
drop table ack;
end;
... consegue. O mesmo segue acima para a tentativa proc original. Assim...
Minha pergunta é esta
Qual é a diferença (e por que está presente) na reserva de nome de objeto para TempDB
objetos em oposição aos bancos de dados do usuário. Nenhuma das referências do Logical Query Processing nem das referências de comando DDL que revi parecem explicar isso.
fonte
Respostas:
Isso não tem nada a ver com reservas de nome de objeto no TempDB ou com o tempo de execução. Isso é simplesmente o analisador que não consegue seguir os caminhos lógicos ou de código que garantem que seu código não possa tentar criar essa tabela duas vezes. Observe que você obtém exatamente o mesmo erro (sem tempo de execução!) Se apenas clicar no botão Analisar ( Ctrl+ F5). Basicamente, se você tiver isso:
O analisador vê isso:
Por que não funciona dessa maneira para tabelas reais , incluindo tabelas de usuários reais criadas no TempDB (observe que também não é específico do banco de dados)? A única resposta que posso sugerir é que o analisador possui um conjunto de regras diferente para as tabelas #temp (também existem muitas outras diferenças). Se você quiser motivos mais específicos, precisará abrir um caso com a Microsoft e verificar se eles fornecerão mais detalhes. Meu palpite é que você será informado: "é assim que funciona".
Mais algumas informações nestas respostas:
fonte