Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

SQL Server - transações aninhadas em um procedimento armazenado


É possível que o trabalho feito pelo SP2 seja revertido e não perca o trabalho feito pelo SP1. Mas para que isso aconteça, você deve escrever seus procedimentos armazenados usando um padrão muito específico, conforme descrito em Tratamento de exceção e transações aninhadas :
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

Nem todos os erros são recuperáveis, existem várias condições de erro das quais uma transação não pode se recuperar, sendo o exemplo mais óbvio o deadlock (você é notificado da exceção de deadlock depois a transação já foi revertida). Ambos SP1 e [email protected] devem ser escritos usando este padrão. Se você tem um SP desonesto, ou quer simplesmente aproveitar os procedimentos armazenados existentes que emitem ROLLBACK sem querer declarações, então sua causa está perdida.