sql >> Base de Datos >  >> RDS >> Sqlserver

SQL Server:transacciones anidadas en un procedimiento almacenado

Es posible revertir el trabajo realizado por SP2 y no perder el trabajo realizado por SP1. Pero para que esto suceda, debe escribir sus procedimientos almacenados usando un patrón muy específico, como se describe en Manejo de excepciones y transacciones anidadas :

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

No todos los errores son recuperables, hay una serie de condiciones de error de las que una transacción no puede recuperarse, el ejemplo más obvio es el punto muerto (se le notifica la excepción de punto muerto después la transacción ya se revirtió). Tanto SP1 como [email protected] tienen que ser escritos usando este patrón. Si tiene un SP deshonesto, o simplemente desea aprovechar los procedimientos almacenados existentes que emiten errores ROLLBACK declaraciones entonces su causa está perdida.