By running 'Test Errors' I get unexpected results. I thought by checking for @@Trancount it would avoid mismatches. Can anyone help me with a better way to rollback errors? I want to rollback all transactions which are nested. Stored procedures can be both nested and on their own.
alter procedure TestErrors
as
begin
    begin try
        begin transaction
        exec TestErrorsInner;
        IF @@TRANCOUNT > 0
            commit transaction;
    end try
    begin catch
        IF @@TRANCOUNT > 0
            rollback transaction;
        select ERROR_MESSAGE();
    end catch
end
alter procedure TestErrorsInner
as
begin
    begin try
        begin transaction
        RAISERROR('Test Error',16,1);
        IF @@TRANCOUNT > 0
            commit transaction;
    end try
    begin catch
        IF @@TRANCOUNT > 0
            rollback transaction;
        select ERROR_MESSAGE();
    end catch
end
Results:
Test Error
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
                        
This is because you are catching a transaction in the TestErrors which is not in Active state.
You have already rolled back your transaction in
Catchblock ofTestErrorsInner. Then again you are trying to do COMMIT/ROLLBACK it inTestErrors. So it is throwing an error.It is your responsibility to Raise an Error explicitly again in
Catchblock ofTestErrorsInner. So that Error will be the input for Parent SP.So your
TestErrorsInnershould be likeNow execute the
TestErrorsStored procedure, you won't get that error.And You can check the Transaction Status with
XACT_STATE()Calling
XACT_STATE()will give result of 0 or 1 or -1 (From MSDN)