Si tiene un bloque TRY / CATCH, la causa probable es que esté detectando una excepción de cancelación de transacción y continúe. En el bloque CATCH siempre debe marcar XACT_STATE()
y manejar las transacciones apropiadas abortadas y no compatibles (condenadas). Si la persona que llama inicia una transacción y la llamada llega, digamos, a un punto muerto (que canceló la transacción), ¿cómo va a comunicar la persona que llama a la persona que llama que la transacción fue cancelada y que no debería continuar con el 'negocio como de costumbre'? La única forma viable es volver a generar una excepción, lo que obliga a la persona que llama a manejar la situación. Si traga silenciosamente una transacción abortada y la persona que llama continúa asumiendo que todavía está en la transacción original, solo el caos puede asegurarse (y el error que obtiene es la forma en que el motor intenta protegerse).
Le recomiendo que revise el manejo de excepciones y las transacciones anidadas, que muestra un patrón que se puede usar con transacciones anidadas y excepciones:
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