Включи xact_abort и попробуй поймать вместе

У меня есть блок try catch в моем sp с просто оператором вставки в try. код ошибки проверки улова, если это нарушение pk, если это так, то выполните обновление. но иногда я получаю "Текущая транзакция не может быть зафиксирована и не может поддерживать операции, которые записывают в файл журнала. Откат транзакции.

Нефиксированная транзакция обнаружена в конце пакета. Транзакция откатывается.", Поэтому я добавил xact_abort, но потом продолжаю получать" Счетчик транзакций после того, как EXECUTE указывает на несовпадающее количество операторов BEGIN и COMMIT.", И я нашел это. http://www.ashishsheth.com/post/2009/08/14/Set-XACT_ABORT-ON-and-TryCatch-block-in-Sql-Server-2005.aspx

если это правда. мой код перехвата не запустится, если в моем блоке try будет ошибка с включенным xact_abort?

1 ответ

Решение

Неверно, по крайней мере в SQL SERVER 2008, что SET XACT_ABORT ON приведет к ошибке, чтобы пропустить блок CATCH:

Вот код, который я пробовал использовать базу данных Northwind

SET XACT_ABORT OFF
BEGIN TRY
    SELECT 1,  @@TRANCOUNT
BEGIN TRAN
    UPDATE [dbo].[Categories]
    SET Description='BLAH'
    WHERE [CategoryID]=2
    SELECT 2,  @@TRANCOUNT

    SELECT 1/0 as whoops


COMMIT
    SELECT 3,  @@TRANCOUNT

END TRY
BEGIN CATCH
    SELECT 'In Catch. Error occured', 4,  @@TRANCOUNT

     IF (XACT_STATE()) = 0
    BEGIN
        SELECT
            N'There is no transaction'

    END;


     IF (XACT_STATE()) = -1
    BEGIN
        SELECT
            N'The transaction is in an uncommittable state.' +
            'Rolling back transaction.'
        ROLLBACK TRANSACTION;
    END;

    -- Test whether the transaction is committable.
    IF (XACT_STATE()) = 1
    BEGIN
        SELECT
            N'The transaction is committable.' +
            'Committing transaction.'
        COMMIT TRANSACTION;   
    END;

END CATCH

Это, очевидно, вызовет ошибку при попадании в оператор SELECT 1/0. Если SET XACT_ABORT OFF, то при достижении блока CATCH значение, возвращаемое функцией XACT_STATE(), равно 1, что приводит к запуску кода, выполняющего транзакцию COMMIT. Когда SET XACT_ABORT включен, возвращаемое значение в блоке CATCH равно -1, поэтому выполняется код, который ROLL возвращает обратно транзакции.

Это основано на:

http://msdn.microsoft.com/en-us/library/ms175976.aspx

Позвольте мне добавить, что в этом конкретном сценарии (попробуйте вставить, если нарушение PK затем поймать и обновить), было бы лучше использовать IF EXISTS (выберите....), чтобы увидеть, есть ли строка, и поместить туда свой оператор UPDATE., Поместите свой оператор INSERT в блок ELSE. Гораздо чище.

Другие вопросы по тегам