J'ai une procédure stockée d'insertion qui alimentera les données dans Table1 et obtiendra la valeur Column1 de Table1 et appellera la deuxième procédure stockée qui alimentera la Table2.
Mais quand j'appelle la deuxième procédure stockée en tant que:
Exec USPStoredProcName
Cela me donne l'erreur comme suit:
Le nombre de transactions après EXECUTE indique un nombre non concordant d'instructions BEGIN et COMMIT. Nombre précédent = 1, nombre actuel = 0.
J'ai lu les réponses à d'autres questions du même genre et je ne suis pas en mesure de trouver exactement où se trouve le décompte des commits.
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 la fonction XACT_STATE()
et gérer les transactions abandonnées et non rentables (condamnées) appropriées. Si votre appelant lance une transaction et que le calee heurte, par exemple, un blocage (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 doit pas continuer comme si de rien n'était? Le seul moyen envisageable est de créer une exception, en obligeant l'appelant à gérer la situation. Si vous avalez en silence une transaction annulée et que l'appelant continue de supposer qu'il se trouve toujours dans la transaction d'origine, seul le chaos peut être vérifié (et l'erreur que vous obtenez est la façon dont le moteur tente de se protéger).
Je vous recommande de passer en revue Traitement des exceptions et transactions imbriquées qui présente un modèle pouvant ê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
J'ai eu ce problème également. Pour moi, la raison était que je faisais
return
commit
au lieu de
commit
return
dans une procédure stockée.
Cela se produit normalement lorsque la transaction est démarrée et qu'elle n'est pas validée ou n'est pas annulée.
Si l'erreur se produit dans votre procédure stockée, cela peut verrouiller les tables de la base de données car la transaction n'est pas terminée en raison d'erreurs d'exécution en l'absence de traitement des exceptions Vous pouvez utiliser la gestion des exceptions comme ci-dessous. SET XACT_ABORT
SET XACT_ABORT ON
SET NoCount ON
Begin Try
BEGIN TRANSACTION
//Insert ,update queries
COMMIT
End Try
Begin Catch
ROLLBACK
End Catch
Sachez que si vous utilisez des transactions imbriquées, une opération ROLLBACK annule toutes les transactions imbriquées, y compris la transaction la plus externe.
Cela pourrait, avec l'utilisation en combinaison avec TRY/CATCH, entraîner l'erreur que vous avez décrite. Voir plus ici .
Cela peut également se produire si votre procédure stockée rencontre un échec de compilation après l'ouverture d'une transaction (par exemple, table introuvable, nom de colonne non valide).
J'ai trouvé que je devais utiliser 2 procédures stockées, une "worker" et une wrapper avec try/catch avec une logique similaire à celle décrite par Remus Rusanu. Le catch worker est utilisé pour gérer les échecs "normaux" et le wrapper pour gérer les erreurs d'échec de compilation.
https://msdn.Microsoft.com/en-us/library/ms175976.aspx
Erreurs non affectées par un TRY… CATCH Construct
Les types d'erreur suivants ne sont pas gérés par un bloc CATCH lorsqu'ils se produisent au même niveau d'exécution que la construction TRY… CATCH:
- Erreurs de compilation, telles que les erreurs de syntaxe, qui empêchent l'exécution d'un lot.
- Erreurs survenues lors de la recompilation au niveau de l'instruction, telles que les erreurs de résolution de nom d'objet survenant après la compilation en raison de la résolution de nom différée.
J'espère que cela aidera quelqu'un d'autre à économiser quelques heures de débogage ...
J'ai rencontré cette erreur une fois après avoir omis cette déclaration de ma transaction.
COMMIT TRANSACTION [MyTransactionName]
Cela peut également dépendre de la façon dont vous appelez le SP à partir de votre code C #. Si le SP renvoie une valeur de type de table, appelez le SP avec ExecuteStoreQuery et si le SP ne renvoie aucune valeur, invoquez le SP avec ExecuteStoreCommand.
J'ai eu le même message d'erreur, mon erreur était que j'avais un point-virgule à la fin de la ligne COMMIT TRANSACTION
Pour moi, après un débogage important, le correctif était un simple lancer manquant; déclaration dans la capture après la restauration. Sans cela, ce message d'erreur laide est ce que vous vous retrouvez avec.
begin catch
if @@trancount > 0 rollback transaction;
throw; --allows capture of useful info when an exception happens within the transaction
end catch
Assurez-vous de ne pas avoir plusieurs transactions dans la même procédure/requête, dont une ou plusieurs sont laissées sans engagement.
Dans mon cas, j'avais accidentellement une instruction BEGIN TRAN dans la requête
À mon avis, la réponse acceptée est dans la plupart des cas une surpopulation.
La cause de l'erreur est souvent l'inadéquation de BEGIN et COMMIT, comme l'indique clairement l'erreur. Cela signifie utiliser:
Begin
Begin
-- your query here
End
commit
au lieu de
Begin Transaction
Begin
-- your query here
End
commit
l'omission de la transaction après le début entraîne cette erreur!