Als u foutbericht 3902, niveau 16 ontvangt, met de tekst "Het COMMIT TRANSACTION-verzoek heeft geen overeenkomstige BEGIN TRANSACTION", komt dat waarschijnlijk omdat u een verdwaalde COMMIT
hebt verklaring.
U kunt dit krijgen door foutafhandeling te implementeren en te vergeten dat u de transactie al ergens anders in uw code heeft vastgelegd of teruggedraaid.
Voorbeeld van fout
Hier is een eenvoudig voorbeeld om de fout aan te tonen:
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Resultaat:
(7 rows affected) Msg 3902, Level 16, State 1, Line 2 The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Dit gebeurt als uw SET IMPLICIT_TRANSACTIONS
is OFF
. Zie hieronder wat er gebeurt als SET IMPLICIT_TRANSACTIONS
is ON
.
Voorbeeld van fout door foutafhandeling
U kunt dit krijgen door foutafhandeling te implementeren en te vergeten dat u de transactie al ergens anders in uw code heeft vastgelegd of teruggedraaid.
Bijvoorbeeld:
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;
Resultaat:
(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.
In dit geval had ik al COMMIT TRANSACTION
in de TRY
blok. Dus tegen de tijd dat de tweede COMMIT TRANSACTION
werd aangetroffen, was de transactie al uitgevoerd.
We zouden hetzelfde zien, zelfs als de transactie een fout had aangetroffen en werd teruggedraaid. Een rollback beëindigt de transactie, en daarom is er geen verdere COMMIT
verklaringen zijn vereist.
Dus om dit probleem op te lossen, verwijderen we gewoon de laatste COMMIT TRANSACTION
, en de transactiecode ziet er als volgt uit:
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
Impliciete transacties
Als u impliciete transacties heeft ingeschakeld, krijgt u mogelijk andere resultaten dan in het eerste voorbeeld.
Als we IMPLICIT_TRANSACTIONS
. instellen naar ON
, dit is wat we krijgen:
SET IMPLICIT_TRANSACTIONS ON;
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Resultaat:
+---------------------------------+----------------+ | 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)
Er treedt geen fout op.
Dit komt omdat bepaalde T-SQL-instructies automatisch een transactie starten wanneer ze worden uitgevoerd. Het is alsof ze worden voorafgegaan door een onzichtbare BEGIN TRANSACTION
verklaring.
Wanneer IMPLICIT_TRANSACTIONS
is OFF
, worden deze uitspraken automatisch vastgelegd. Het is alsof ze worden opgevolgd door een onzichtbare COMMIT TRANSACTION
uitspraak. In dit scenario bevindt de transactie zich in de autocommit-modus.
Wanneer IMPLICIT_TRANSACTIONS
is ON
, er is geen onzichtbare COMMIT TRANSACTION
uitspraak. Deze instructies worden nog steeds gestart door een onzichtbare BEGIN TRANSACTION
, maar ze moeten expliciet worden beëindigd.
Een impliciete transactie blijft in uitvoering totdat deze ofwel expliciet wordt vastgelegd of expliciet wordt teruggedraaid.
Daarom is in dit voorbeeld onze verdwaalde COMMIT TRANSACTION
verklaring eigenlijk nodig was om de impliciete transactie te beëindigen.