Собрав воедино быстрый процесс для отладки, я столкнулся с ошибкой в компиляторе.
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;
Попытка вышеупомянутого возвращает следующую ошибку
Сообщение 2714, уровень 16, состояние 1, процедура spFoo, строка 19
В базе данных уже есть объект с именем #bar.
В понятном для человека смысле, процесс, кажется, в порядке: только один select into
оператор когда-либо будет выполнен, так как они заключены в if-else
блоки. Впрочем, SQL-сервер не может подтвердить, что операторы логически исключены друг из друга. Возможно, еще более запутанным является то, что ошибка остается, когда drop table #foo
она помещается в блок if-else (который, как предполагается, сообщит компилятору об освобождении имени объекта), как показано ниже.
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;
Сам процесс в порядке. Я смирился с этим и написал операторы create table #foo( ... )
and insert #foo ( ... )
, я пытался пропустить select * into
синтаксис. На данный момент я просто пытаюсь понять, почему компилятор помешался на мне с синтаксисом lazy-guy. Единственное, о чем я могу думать, это то, что команда DDL резервирует имя объекта IN TEMPDB .
Почему жирный текст?
create proc spIck
as
begin
create table #ack ( col1 int );
drop table #ack;
create table #ack ( colA char( 1 ) );
drop table #ack;
end;
Это происходит с тем же кодом ошибки, что и выше. Но следующее ...
create proc spIck
as
begin
create table ack ( col1 int );
drop table ack;
create table ack ( colA char( 1 ) );
drop table ack;
end;
... успешно. То же самое следует выше к первоначальной попытке процедуры. Так...
Мой вопрос это
В чем разница (и почему она присутствует) в резервировании имен TempDB
объектов для объектов в отличие от пользовательских баз данных. Ни одна из ссылок на логическую обработку запросов или ссылок на команды DDL, которые я рассмотрел, не объясняет этого.
источник
Ответы:
Это не имеет ничего общего с резервированием имени объекта в TempDB или чем-либо, связанным с временем выполнения. Это просто синтаксический анализатор, неспособный следовать логике или путям кода, который гарантирует, что ваш код не может попытаться создать эту таблицу дважды. Обратите внимание, что вы получите точно такую же ошибку (не во время выполнения!), Если просто нажать кнопку Parse ( Ctrl+ F5). В основном, если у вас есть это:
Парсер видит это:
Почему это не работает таким образом для реальных таблиц, включая реальные пользовательские таблицы, созданные в TempDB (обратите внимание, что это также не зависит от базы данных)? Единственный ответ, который я могу предложить, состоит в том, что синтаксический анализатор имеет другой набор правил для таблиц #temp (также есть много других отличий). Если вам нужны более конкретные причины, вам нужно открыть дело в Microsoft и посмотреть, предоставят ли они вам дополнительную информацию. Я думаю, вам скажут: «Вот как это работает».
Еще немного информации в этих ответах:
источник