Как работает SET NOEXEC ON?

У меня такой код:

-- start of code
set noexec off

declare @requiredVersion int
declare @currentVersion int

set @requiredVersion = 5
set @currentVersion = 4

if (@currentVersion < @requiredVersion)
begin
    print 'Please update your DB to version 5 before running this script.'
    set noexec on
end

go
-- print 'Dummy'
insert into tblFooBar(name) values ('AAA')
go

set noexec off
-- end of code

Обратите внимание, что таблица "tblfoobar" не существует в базе данных. Когда я запускаю этот код, появляется сообщение:

Пожалуйста, обновите вашу БД до версии 5 перед запуском этого скрипта.
Сообщение 208, уровень 16, состояние 1, строка 1
Недействительное имя объекта "tblFooBar".

Я ожидал, что установка noexec на ON может не дать части сообщения «Msg 208».

Затем снова "set noexec on" компилирует код, а не выполняет его. Я предполагаю, что попытка вставить что-то в таблицу, которой не существует, является ошибкой времени компиляции. В таком случае должна появиться ошибка «пропавший объект».

Теперь позвольте мне рассказать вам о странном поведении, которое я наблюдал. Если я уберу комментарий из строки «- Вывести пустышку» »

-- start of code
set noexec off

declare @requiredVersion int
declare @currentVersion int

set @requiredVersion = 5
set @currentVersion = 4

if (@currentVersion < @requiredVersion)
begin
    print 'Please update your DB to version 5 before running this script.'
    set noexec on
end
go
print 'Dummy'
insert into tblFooBar(name) values ('AAA')
go

и выполните код, я получаю только следующее сообщение.

Пожалуйста, обновите вашу БД до версии 5 перед запуском этого скрипта.

На этот раз сообщения об отсутствии таблицы нет.

Может кто-нибудь объяснить мне это поведение? Спасибо.

Ответов (2)

Я проверил приведенный выше код, и он отлично работает. Он не выдает сообщения об ошибке для отсутствующего объекта.

set noexec off

declare @requiredVersion int
declare @currentVersion int

set @requiredVersion = 5
set @currentVersion = 4

if (@currentVersion < @requiredVersion)
begin
    print 'Please update your DB to version 5 before running this script.'
    set noexec on--> here we are setting NOEXEC on
end

go
-- print 'Dummy'
insert into tblFooBar(name) values ('AAA')
go

set noexec off
-- end of code

Поскольку NOEXEC включен, приведенный ниже код будет скомпилирован, а не выполнен, следовательно, он не будет выдавать никаких сообщений об ошибках.

Я бы не ожидал, что будет корректно использовать "set noexec" в условном выражении, как вы это сделали, но на самом деле это кажется допустимым.

Такое поведение, похоже, связано с тем, что это оператор DDL. Если вы замените вставку оператором печати или простым запросом выбора, сценарий будет работать должным образом.

Кстати, если я хочу сделать что-то подобное, я использую следующий подход:

    создать proc tmproc_foobar как
       СОЗДАТЬ ТАБЛИЦУ tblFooBar (имя nvarchar (20))
    идти

    если существует (выберите 1 из sysobjects, где type = 'U' и name = 'tblFooBar')
         exec tmproc_foobar
    идти

    сбросить proc tmproc_foobar
    идти

SQL Server позволяет создавать хранимую процедуру с несуществующим объектом, поэтому вы можете создать процедуру, выполнить ее условно, а затем отбросить. Вот так у меня длинный скрипт обновления, который условно добавляет в мою базу данных любые недостающие объекты.

Возможно, вы могли бы это приспособить. Тогда вам вообще не нужен noexec, потому что вы избегаете всей проблемы недопустимых объектов.