SQL Server не соответствует количеству вложенных транзакций операторов BEGIN и COMMIT

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

Это мой шаблон

CREATE PROCEDURE DoSomething
AS
BEGIN
SET NOCOUNT ON
DECLARE @trans INTEGER = @@TRANCOUNT

IF (@trans > 0)
    SAVE TRANSACTION SavePoint
ELSE
    BEGIN TRANSACTION

BEGIN TRY
    -- code with a check that does a THROW if the requirements aren't met
    IF (@trans = 0)
        COMMIT TRANSACTION
END TRY

BEGIN CATCH
    IF (@trans > 0)
        ROLLBACK TRANSACTION SavePoint
    ELSE
        ROLLBACK TRANSACTION

    ;THROW
END CATCH
END

Если я заменю THROW в блоке TRY на RAISERROR, проблема останется.

Результаты теста:

Сценарий сбоя EXEC в транзакции: правильный результат (выдает правильное сообщение об ошибке)

Сценарий успеха EXEC в транзакции: выдает неожиданную ошибку.

Число транзакций после EXECUTE указывает на несовпадающее количество операторов BEGIN и COMMIT. Предыдущий счет = 1, текущий счет = 2.

Сценарий сбоя EXEC вне транзакции: выдает ожидаемую ошибку.

Сценарий успеха EXEC вне транзакции: выдает неожиданную ошибку. Ошибка та же, что и выше, но каждый раз, когда вы ее выполняете, она увеличивается на -1. Означает ли это, что каждый раз, когда больше вещей остается незафиксированным?

Вот как выглядит тест:

BEGIN TRANSACTION
  EXEC ...
ROLLBACK TRANSACTION

Кто-нибудь знает, что идет не так?

1 ответ

Раскомментировать вар

CREATE PROCEDURE DoSomething
AS
BEGIN
SET NOCOUNT ON
DECLARE @trans INTEGER = @@TRANCOUNT

IF (@trans > 0)
    SAVE TRANSACTION SavePoint
ELSE
    BEGIN TRANSACTION

BEGIN TRY
    DECLARE @f float;
    SET @f = 0;
    --var 1.
    --print  1/0
    --var 2.
    print LOG(@f)     
    --var ok
    --print 'ok'
END TRY

BEGIN CATCH             
    IF (@trans > 0 AND XACT_STATE() <> -1)
    BEGIN
        PRINT 'ROLLBACK SavePoint'
        ROLLBACK TRANSACTION SavePoint
    END
    PRINT 'Error'
END CATCH
END

И выполнить

BEGIN TRANSACTION   
EXEC DoSomething 

IF XACT_STATE() = -1      
BEGIN   
    PRINT 'ROLLBACK XACT'
    ROLLBACK 
END

IF @@TRANCOUNT > 0 
BEGIN
    PRINT 'COMMIT'
    COMMIT 
END
Другие вопросы по тегам