Как предотвратить завершение будущих пакетов при ошибке и откат? - PullRequest
0 голосов
/ 12 июля 2011

Если у меня следующий SQL-запрос

CREATE TABLE #t1
    (a INT NOT NULL PRIMARY KEY);
SET XACT_ABORT ON
go

BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1);
INSERT INTO #t1 VALUES (2);
INSERT INTO #t1 VALUES (3);
INSERT INTO #t1 VALUES (2); -- PK violation error
go

INSERT INTO #t1 VALUES (4);
go

COMMIT TRANSACTION

SET XACT_ABORT OFF

Когда я запускаю запрос, я получаю этот вывод

(затронут 1 строка)

(Затронуты 1 строка)

(затронуты 1 строка) Сообщение 2627, уровень 14, состояние 1, строка 7 Нарушение ограничения PRIMARY KEY 'PK_ # t1 _ __ _ _ _66D536B1.Невозможно вставить повторяющийся ключ в объект 'dbo. # T1'.

(затронут 1 строка) Msg 102, уровень 15, состояние 1, строка 8 Неверный синтаксис рядом с '# t1'.

И значение # t1 равно

a
-----------
4

Что мне нужно сделать, чтобы скрипт прервал работу и не запустил второй пакет?

РЕДАКТИРОВАТЬ:

Пробное решение JNK

begin try
BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1)
INSERT INTO #t1 VALUES (2)
INSERT INTO #t1 VALUES (3)
INSERT INTO #t1 VALUES (2) -- PK violation error
go

INSERT INTO #t1 VALUES (4)
go

COMMIT TRANSACTION

end try
begin catch 
IF @@trancount > 0 Rollback

END catch

select * from #t1

truncate table #t1

Однако я получаю этот вывод

Msg 102, Level 15, State 1, Line 6
Incorrect syntax near ')'.

(1 row(s) affected)
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'begin'.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'END'.

И таблица все еще содержит 4 после

EDIT2:

ошибки с уловом try вызваны оператором GO, который мне нужен для моего реального сценария вместо этого контрольного примера.так что, похоже, попытка / отлов не будет работать в этом случае.

Ответы [ 2 ]

1 голос
/ 12 июля 2011

Добавить обработку ошибок:

BEGIN TRY
<your query>
END TRY
BEGIN CATCH

IF @@TRANCOUNT > 0 ROLLBACK    

<other error reporting processes>

END CATCH

ROLLBACK является необязательным и отменяет любые вставки, которые были завершены до возникновения ошибки.Вы также можете добавить несколько транзакций, так что если, скажем, первые 3 вставки не зависят от некоторых других вещей позже, оберните их в транзакцию и зафиксируйте ее, а затем сделайте еще один переход для несвязанного процесса.

0 голосов
/ 12 июля 2011
begin try
   begin transaction

    INSERT INTO #t1 VALUES (1);
    INSERT INTO #t1 VALUES (2);
    INSERT INTO #t1 VALUES (3);
    INSERT INTO #t1 VALUES (2); 
    INSERT INTO #t1 VALUES (4);

   commit
end try
begin catch
    if @@trancount > 0
        rollback

    declare @errmsg nvarchar(4000), @errseverity int
    select @errmsg = error_message(), @errseverity = error_severity()

    raiserror(@errmsg, @errseverity, 1)
end catch

Из MSDN: " интерпретирует GO как сигнал о том, что они должны отправить текущий пакет операторов Transact-SQL экземпляру SQL Server. Текущий пакет операторов состоит из всех операторов, введенных послепоследний GO или после начала специального сеанса или сценария, если это первый GO .

Оператор Transact-SQL не может занимать ту же строку, что и команда GO. Однакострока может содержать комментарии."

...