Si vous recevez l'erreur Msg 3902, niveau 16, qui indique "La requête COMMIT TRANSACTION n'a pas de BEGIN TRANSACTION correspondante", c'est probablement parce que vous avez un COMMIT
errant. déclaration.
Vous pourriez obtenir cela en raison de la mise en œuvre de la gestion des erreurs et de l'oubli que vous avez déjà validé ou annulé la transaction ailleurs dans votre code.
Exemple d'erreur
Voici un exemple simple pour illustrer l'erreur :
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Résultat :
(7 rows affected) Msg 3902, Level 16, State 1, Line 2 The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Cela se produira si votre SET IMPLICIT_TRANSACTIONS
est OFF
. Voir ci-dessous ce qui se passe lorsque SET IMPLICIT_TRANSACTIONS
est ON
.
Exemple d'erreur due à la gestion des erreurs
Vous pourriez obtenir cela en raison de la mise en œuvre de la gestion des erreurs et de l'oubli que vous avez déjà validé ou annulé la transaction ailleurs dans votre code.
Par exemple :
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
VALUES ( 5006, SYSDATETIME(), 1006 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 1, 1, 20, 25.99 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 2, 7, 120, 9.99 );
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
COMMIT TRANSACTION;
Résultat :
(1 row affected) (1 row affected) (1 row affected) Msg 3902, Level 16, State 1, Line 20 The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Dans ce cas, j'avais déjà COMMIT TRANSACTION
dans le TRY
bloc. Ainsi, au moment où le deuxième COMMIT TRANSACTION
a été rencontré, la transaction avait déjà été validée.
Nous verrions la même chose même si la transaction avait rencontré une erreur et avait été annulée. Une annulation mettra fin à la transaction et, par conséquent, aucun autre COMMIT
déclarations sont obligatoires.
Donc, pour résoudre ce problème, nous supprimerions simplement le dernier COMMIT TRANSACTION
, et le code de transaction ressemblerait à ceci :
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
VALUES ( 5006, SYSDATETIME(), 1006 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 1, 1, 20, 25.99 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 2, 7, 120, 9.99 );
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
Transactions implicites
Si vous avez activé les transactions implicites, vous pourriez obtenir des résultats différents du premier exemple.
Si nous définissons IMPLICIT_TRANSACTIONS
sur ON
, voici ce que nous obtenons :
SET IMPLICIT_TRANSACTIONS ON;
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Résultat :
+---------------------------------+----------------+ | ProductName | ProductPrice | |---------------------------------+----------------| | Left handed screwdriver | 25.99 | | Long Weight (blue) | 14.75 | | Long Weight (green) | 11.99 | | Sledge Hammer | 33.49 | | Chainsaw | 245.00 | | Straw Dog Box | 55.99 | | Bottomless Coffee Mugs (4 Pack) | 9.99 | +---------------------------------+----------------+ (7 rows affected)
Aucune erreur ne se produit.
En effet, certaines instructions T-SQL démarrent automatiquement une transaction lors de leur exécution. C'est comme s'ils étaient précédés d'un BEGIN TRANSACTION
invisible déclaration.
Lorsque IMPLICIT_TRANSACTIONS
est OFF
, ces instructions sont automatiquement validées. C'est comme s'ils étaient remplacés par un COMMIT TRANSACTION
invisible déclaration. Dans ce scénario, la transaction est en mode autocommit.
Lorsque IMPLICIT_TRANSACTIONS
est ON
, il n'y a pas de COMMIT TRANSACTION
invisible déclaration. Ces instructions sont toujours lancées par un BEGIN TRANSACTION
invisible , mais ils doivent être terminés explicitement.
Une transaction implicite reste en cours jusqu'à ce qu'elle soit explicitement validée ou explicitement annulée.
Par conséquent, dans cet exemple, notre erreur COMMIT TRANSACTION
était en fait nécessaire pour mettre fin à la transaction implicite.