Si vous avez un bloc TRY / CATCH, la cause probable est que vous détectez une exception d'abandon de transaction et que vous continuez. Dans le bloc CATCH, vous devez toujours vérifier XACT_STATE()
et gérer les transactions avortées et non validables (condamnées) appropriées. Si votre appelant commence une transaction et que l'appelant rencontre, par exemple, une impasse (qui a annulé la transaction), comment l'appelé va-t-il communiquer à l'appelant que la transaction a été annulée et qu'elle ne devrait pas continuer avec le «statu quo»? Le seul moyen possible est de relancer une exception, forçant l'appelant à gérer la situation. Si vous avalez silencieusement une transaction annulée et que l'appelant continue de supposer 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 de passer en revue la gestion des exceptions et les 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