Mettendo insieme una procedura rapida per aiutare con il debug, mi sono imbattuto in quello che sembra essere un errore nel compilatore.
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;
Tentare quanto sopra restituisce il seguente errore
Messaggio 2714, livello 16, stato 1, procedura spFoo, riga 19
Nel database è già presente un oggetto denominato "#bar".
In un senso leggibile dall'uomo, il proc sembra andare bene: select into
sarà mai eseguita solo un'istruzione poiché sono racchiuse nei if-else
blocchi. Molto bene, tuttavia, il server SQL non può confermare che le istruzioni siano logicamente escluse l'una dall'altra. Forse forse più confuso è che l'errore rimane quando drop table #foo
viene inserito all'interno del blocco if-else (che si presume direbbe al compilatore di deallocare il nome dell'oggetto) come di seguito.
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;
Lo stesso proc va bene. L'ho succhiato e ho scritto le dichiarazioni create table #foo( ... )
e insert #foo ( ... )
, avevo cercato di saltare con la select * into
sintassi. A questo punto, sto solo cercando di capire perché il compilatore è saltato fuori con la sintassi del tipo pigro. L'unica cosa che mi viene in mente è che il comando DDL riserva il nome dell'oggetto IN TEMPDB .
Perché il testo in grassetto?
create proc spIck
as
begin
create table #ack ( col1 int );
drop table #ack;
create table #ack ( colA char( 1 ) );
drop table #ack;
end;
Questo non riesce con lo stesso codice di errore di cui sopra. Ma il seguente ...
create proc spIck
as
begin
create table ack ( col1 int );
drop table ack;
create table ack ( colA char( 1 ) );
drop table ack;
end;
... ci riesce. Lo stesso vale per il tentativo proc originale. Così...
La mia domanda è questa
Qual è la differenza (e perché è presente) nella prenotazione del nome oggetto per gli TempDB
oggetti rispetto ai database degli utenti. Nessuno dei riferimenti sull'elaborazione della query logica né i riferimenti ai comandi DDL che ho esaminato sembrano spiegare questo.