web-dev-qa-db-fra.com

Le nombre de transactions après EXECUTE indique un nombre non concordant d'instructions BEGIN et COMMIT. Nombre précédent = 1, nombre actuel =

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.

71
Vignesh Kumar A

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
85
Remus Rusanu

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.

46
seguso

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

La source

15

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 .

9
niklasolsn

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 ...

2
Justin

J'ai rencontré cette erreur une fois après avoir omis cette déclaration de ma transaction.

COMMIT TRANSACTION [MyTransactionName]
1
Ken Palmer

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.

1
Rajan Tikare

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

1
Zsombor Zsuffa

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
0
hexpoint

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

0
Sen Alexandru

À 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!

0
omostan