sqlsql-server-2012sqlexception

Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0


I have an Insert stored procedure which will feed data to Table1 and get the Column1 value from Table1 and call the second stored procedure which will feed the Table2.

But when I call The second stored procedure as:

Exec USPStoredProcName

I get the following error:

Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.

I have read the answers in other such questions and am unable to find where exactly the commit count is getting messed up.


Solution

  • If you have a TRY/CATCH block then the likely cause is that you are catching a transaction abort exception and continue. In the CATCH block you must always check the XACT_STATE() and handle appropriate aborted and uncommitable (doomed) transactions. If your caller starts a transaction and the calee hits, say, a deadlock (which aborted the transaction), how is the callee going to communicate to the caller that the transaction was aborted and it should not continue with 'business as usual'? The only feasible way is to re-raise an exception, forcing the caller to handle the situation. If you silently swallow an aborted transaction and the caller continues assuming is still in the original transaction, only mayhem can ensure (and the error you get is the way the engine tries to protect itself).

    I recommend you go over Exception handling and nested transactions which shows a pattern that can be used with nested transactions and exceptions:

    create procedure [usp_my_procedure_name]
    as
    begin
        set nocount on;
        declare @trancount int;
        set @trancount = @@trancount;
        begin try
            if @trancount = 0
                begin transaction
            else
                save transaction usp_my_procedure_name;
    
            -- Do the actual work here
    
    lbexit:
            if @trancount = 0
                commit;
        end try
        begin catch
            declare @error int, @message varchar(4000), @xstate int;
            select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
            if @xstate = -1
                rollback;
            if @xstate = 1 and @trancount = 0
                rollback
            if @xstate = 1 and @trancount > 0
                rollback transaction usp_my_procedure_name;
    
            raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
        end catch
    end
    go