SQL Server: как прервать серию пакетов в Query Analyzer?

У меня есть ряд операторов T-SQL, разделенных специальным ключевым словом разделителя пакетов Query Analyzer:

GO

Если один пакет не работает, мне нужно, чтобы Query Analyzer не пробовал последующие пакеты - я хочу, чтобы он прекратил обработку серии пакетов.

Например:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go

PRINT 'This should not run'
go

Вывод:

This runs
Server: Msg 8134, Level 16, State 1, Line 2
Divide by zero error encountered.
This should not run

Возможный?


Обновлять

Примером этого на практике может быть:

 sp_rename 'Shelby', 'Kirsten'
 go

 DROP VIEW PeekAView
 go

 CREATE VIEW PeekAViewAS 
 SELECT * FROM Kirsten
 go

person Ian Boyd    schedule 29.05.2009    source источник
comment
у вас сработал какой-либо из этих ответов?   -  person KM.    schedule 30.05.2009
comment
Это очень правильный вопрос, почему так много голосов против?   -  person Andomar    schedule 30.05.2009


Ответы (6)


Вот как бы я это сделал:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go
if (@@error <> 0)
    Begin
    set nocount on
    set noexec on
    End
GO

PRINT 'This should not run'
go

set noexec off
set nocount off
GO

Режим «noexec» помещает SSMS в состояние, в котором он просто компилирует T-SQL и фактически не выполняет его. Это похоже на случайное нажатие кнопки «Разобрать» на панели инструментов (Ctrl + F5) вместо «Выполнить» (F5).

Не забудьте снова отключить noexec в конце вашего скрипта. В противном случае пользователи будут сбиты с толку постоянным сообщением «Команда (и) успешно выполнена». Сообщения.

Я использую проверку на наличие ошибки @@ в следующем пакете вместо блоков TRY CATCH. Использование ошибки @@ в следующем пакете приведет к обнаружению ошибок компиляции, таких как «таблица не существует».

В дополнение к режиму noexec я также переключаю режим nocount. При включенном режиме noexec и выключенном nocount ваши запросы все равно будут сообщать о сообщении «(затронутых строк: 0)». Сообщение всегда содержит нулевые строки, потому что вы находитесь в режиме noexec. Однако включение nocount подавляет эти сообщения.

Также обратите внимание, что при запуске SQL Server 2005 команда, которую вы пропускаете, может по-прежнему выдавать сообщения об ошибках, если она ссылается на таблицу, которая не существует, и команду, если это первая команда в пакете. Принуждение команды быть второй командой в пакете с фиктивным оператором печати может подавить это. См. Ошибка MS # 569263, чтобы узнать больше.

person Timothy Klenke    schedule 23.05.2012
comment
За годы, прошедшие с тех пор, как я задал этот вопрос, я узнал, что это делает инструмент сравнения SQL (не SQL Compare). После каждого оператора проверяйте, продолжается ли транзакция, и если нет SET NOEXEC ON - person Ian Boyd; 23.05.2012
comment
Не работает последующие партии. Если бы у вас был запрос, который создает таблицы вместо вывода на экран в предпоследнем пакете, он бы создал таблицу. Значит, код неправильный. - person Trismegistos; 20.06.2012
comment
Trismegistos, я заменил PRINT «Это не должно выполняться» оператором Create Table, и таблица не создается. Можете опубликовать пример? - person Timothy Klenke; 04.10.2012
comment
+1 Очень элегантно. Теперь я использую это в сценарии резервного копирования сервера, который проходит через все базы данных: если тест одной базы данных завершается неудачно, последующие операторы против нее завершаются этим подходом noexec. Некоторые из успешно пропущенных пакетных операторов включают: xp_create_subdir, журнал резервного копирования, восстановление, проверка только. Я бы назвал это победой. Спасибо. MS SQL Server 2008 R2. - person Joe Creighton; 24.09.2013

Вы можете активировать опцию меню «Query, SQLCMD Mode» и поместить следующее в начало скрипта:

:on error exit

Это остановит выполнение при возникновении ошибки, даже если есть последующие пакеты.

Просто убедитесь, что вы случайно не запустили сценарий без включенного режима SQLCMD, потому что вы получите типичное поведение, при котором ошибки игнорируются.

person Jason Kresowaty    schedule 13.10.2009
comment
Кроме того, возникающие ошибки (RAISERROR) не отображаются в выходных данных. - person Bernhard Hofmann; 12.09.2014

Когда мне нужно это сделать, я выдаю RAISERROR серьезности 20. Это или выше убьет текущее соединение и предотвратит выполнение последующих «пакетов GO». Да, это может быть неудобно, но работает.

person Philip Kelley    schedule 13.10.2009
comment
Согласно stackoverflow.com/questions/659188/, ему также нужен" с журналом ". Либо приведенное выше предложение, либо метод set noexec on, упомянутый в связанном вопросе, являются наиболее элегантными способами достижения этого, IMO. - person JT.; 15.12.2010
comment
Кроме того, для этого требуются права sysadmin / alter на трассировку, которых у некоторых людей может не быть. Уровни серьезности от 19 до 25 могут быть указаны только членами фиксированной серверной роли sysadmin или пользователями с разрешениями ALTER TRACE. Источник: MSDN RAISERROR - person Bernhard Hofmann; 12.09.2014

Создайте временную таблицу; и обновлять его после каждого шага (в случае успеха); а затем проверьте успешность предыдущего шага, сверяясь с таблицей.

create table #ScriptChecker (SuccessfullStep int)

-- Do Step One
Insert into #ScriptChecker
Select 1

-- Step 2
If exists (select * from #ScriptChecker where SuccessfullStep = 1)
-- Do Step 2 ...
person u07ch    schedule 29.05.2009
comment
+1. Возможно, есть способ получше, но это так просто, я удивляюсь, почему я никогда об этом не подумал. - person Lieven Keersmaekers; 29.05.2009
comment
Более-менее, как MS сами это делают в мастере сценариев - person u07ch; 29.05.2009
comment
Это не сработает, если одним из операторов является CREATE VIEW. - person Ian Boyd; 21.09.2009
comment
Вы можете проверить наличие представления и использовать его для управления вставкой в ​​таблицу транзакций. - person u07ch; 22.09.2009
comment
Что делать, если вы обновляете существующее представление? Или функция, процедура или триггер? - person Philip Kelley; 13.10.2009

основан на идее @ u07ch, но вставлять только при неудаче ...

create table #test (failure  int)

if not exists (select * from #test)
BEGIN
    print 'one' --sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'two'--sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'three' ---SQL SERVER 2000 version
    --error--
    SELECT 0/0, 'This causes an error'
    IF @@ERROR!=0
    BEGIN
        insert into #test values (1)
        PRINT 'ERROR'
    END
end 
go

if not exists (select * from #test)
BEGIN
    print 'three'  ---SQL SERVER 2005/2008 version
    BEGIN TRY
    --error--
        SELECT 0/0, 'This causes an error'
    END TRY
    BEGIN CATCH
        insert into #test values (1)
        PRINT 'ERROR'
    END CATCH
END
go

if not exists (select * from #test)
BEGIN
    --sql here
    print 'four'
END
go

выход 2000:

one
two
three

----------- --------------------
Msg 8134, Level 16, State 1, Line 7
Divide by zero error encountered.

(1 row(s) affected)

ERROR

результат 2005/2008:

one
two
three

----------- --------------------

(0 row(s) affected)

(1 row(s) affected)

ERROR
person KM.    schedule 29.05.2009
comment
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? может кто-нибудь сказать мне, почему по этому вопросу так много голосов против? получить жизнь, они всего лишь очки и жизнь будет продолжаться с ними или без них? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - person KM.; 29.05.2009
comment
Разве это не очевидно? Этот вопрос бесполезен и непонятен. /сарказм - person Ian Boyd; 30.05.2009
comment
‹Sarcasm› Возможно, ваш ответ был слишком подробным ‹/sarcasm› Более того, он также должен работать лучше (хотя и немного), чем исходный, поскольку он вставляется только в случае ошибки .... Вы недавно флиртовали с чьей-то женой? ;-) - person M.Turrini; 04.06.2009

Эрланд Соммарског из группы разработчиков microsoft.public.sqlserver.programming пришел к очень хорошей идее:

В сценарии изменения, таком как тот, который вы опубликовали, вы должны быть защищенными и начинать каждый пакет с IF @@ trancount> 0.

С использованием

IF @@trancount > 0 

намного чище.

person Ian Boyd    schedule 03.06.2009
comment
Это не для всего содержимого партии. - person Ian Boyd; 21.09.2009