Si vous avez un bloc TRY/CATCH, la cause probable est que vous interceptez une exception d'abandon de transaction et que vous continuez. Dans le bloc CATCH, vous devez toujours vérifier le XACT_STATE()
et gérer les transactions avortées et non engageables (condamnées) appropriées. Si votre appelant démarre une transaction et que le calee rencontre, par exemple, une impasse (qui a interrompu la transaction), comment l'appelé va-t-il communiquer à l'appelant que la transaction a été interrompue et qu'elle ne devrait pas continuer avec le "business as usual" ? Le seul moyen possible est de relancer une exception, forçant l'appelant à gérer la situation. Si vous avalez silencieusement une transaction abandonnée et que l'appelant continue en supposant qu'il est toujours dans la transaction d'origine, seul le chaos peut garantir (et l'erreur que vous obtenez est la façon dont le moteur essaie de se protéger).
Je vous recommande d'aller sur Gestion des exceptions et transactions imbriquées qui montre un modèle qui peut être utilisé avec des transactions imbriquées et des 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