SQL Server: как прервать серию пакетов в Query Analyzer? - PullRequest
4 голосов
/ 29 мая 2009

У меня есть ряд операторов 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

Ответы [ 6 ]

8 голосов
/ 23 мая 2012

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

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 и фактически не выполняет его. Это похоже на случайное нажатие кнопки панели инструментов Parse (Ctrl + F5) вместо Execute (F5).

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

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

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

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

4 голосов
/ 13 октября 2009

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

:on error exit

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

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

2 голосов
/ 13 октября 2009

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

1 голос
/ 29 мая 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
1 голос
/ 29 мая 2009

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

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 ...
0 голосов
/ 03 июня 2009

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

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

Использование

IF @@trancount > 0 

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

...