Mettre en place un proc quickie pour aider au débogage, j'ai rencontré ce qui semble être une erreur dans le compilateur.
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;
La tentative ci-dessus renvoie l'erreur suivante
Msg 2714, niveau 16, état 1, procédure spFoo, ligne 19
Il existe déjà un objet nommé '#bar' dans la base de données.
Dans un sens lisible par l'homme, le proc semble être bien: une seule select into
instruction sera jamais exécutée car elles sont enveloppées à l'intérieur des if-else
blocs. Très bien cependant, SQL Server ne peut pas confirmer que les instructions sont logiquement exclues les unes des autres. Le plus déroutant est peut-être que l'erreur persiste lorsque le drop table #foo
est placé à l'intérieur du bloc if-else (dont on suppose qu'il dirait au compilateur de désallouer le nom de l'objet) comme ci-dessous.
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;
Le proc lui-même est très bien. Je l'ai aspiré et j'ai écrit les déclarations create table #foo( ... )
et insert #foo ( ... )
, j'avais essayé de sauter avec la select * into
syntaxe. À ce stade, j'essaie simplement de comprendre pourquoi le compilateur m'a chié avec la syntaxe paresseuse. La seule chose à laquelle je peux penser est que la commande DDL réserve le nom de l'objet IN TEMPDB .
Pourquoi le texte en gras?
create proc spIck
as
begin
create table #ack ( col1 int );
drop table #ack;
create table #ack ( colA char( 1 ) );
drop table #ack;
end;
Cela échoue avec le même code d'erreur que ci-dessus. Mais ce qui suit ...
create proc spIck
as
begin
create table ack ( col1 int );
drop table ack;
create table ack ( colA char( 1 ) );
drop table ack;
end;
... réussit. La même chose ci-dessus s'applique à la tentative de proc d'origine. Donc...
Ma question est la suivante
Quelle est la différence (et pourquoi est-elle présente) dans la réservation de nom d' TempDB
objet par opposition aux bases de données utilisateur. Aucune des références Logical Query Processing ni des références de commande DDL que j'ai examinées ne semble expliquer cela.