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.