Hvis du modtager fejlmeddelelse 3902, niveau 16, som lyder "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION", er det sandsynligvis fordi du har en omstrejfende COMMIT
erklæring.
Du kan få dette på grund af implementering af fejlhåndtering og glemmer, at du allerede har forpligtet eller rullet tilbage transaktionen et andet sted i din kode.
Eksempel på fejl
Her er et simpelt eksempel til at demonstrere fejlen:
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Resultat:
(7 rows affected) Msg 3902, Level 16, State 1, Line 2 The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Dette vil ske, hvis din SET IMPLICIT_TRANSACTIONS
er OFF
. Se nedenfor for, hvad der sker, når SET IMPLICIT_TRANSACTIONS
er ON
.
Eksempel på fejl på grund af fejlhåndtering
Du kan få dette på grund af implementering af fejlhåndtering og glemmer, at du allerede har forpligtet eller rullet tilbage transaktionen et andet sted i din kode.
For eksempel:
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;
Resultat:
(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.
I dette tilfælde havde jeg allerede COMMIT TRANSACTION
i TRY
blok. Så inden den anden COMMIT TRANSACTION
blev stødt på, var transaktionen allerede blevet begået.
Vi ville se det samme, selvom transaktionen var stødt på en fejl og blev rullet tilbage. En tilbagerulning vil afslutte transaktionen, og derfor ingen yderligere COMMIT
erklæringer er påkrævet.
Så for at løse dette problem ville vi simpelthen fjerne den sidste COMMIT TRANSACTION
, og transaktionskoden ville se sådan ud:
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
Implicitte transaktioner
Hvis du har aktiveret implicitte transaktioner, får du muligvis andre resultater end det første eksempel.
Hvis vi indstiller IMPLICIT_TRANSACTIONS
til ON
, her er hvad vi får:
SET IMPLICIT_TRANSACTIONS ON;
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Resultat:
+---------------------------------+----------------+ | 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)
Der opstår ingen fejl.
Dette skyldes, at visse T-SQL-udsagn automatisk starter en transaktion, når de kører. Det er, som om de blev indledt af en usynlig BEGIN TRANSACTION
erklæring.
Når IMPLICIT_TRANSACTIONS
er OFF
, bliver disse udsagn automatisk begået. Det er, som om de bliver efterfulgt af en usynlig COMMIT TRANSACTION
udmelding. I dette scenarie er transaktionen i autocommit-tilstand.
Når IMPLICIT_TRANSACTIONS
er ON
, der er ingen usynlig COMMIT TRANSACTION
udmelding. Disse udsagn startes stadig af en usynlig BEGIN TRANSACTION
, men de skal afsluttes eksplicit.
En implicit transaktion forbliver i gang, indtil den enten er eksplicit begået eller eksplicit rullet tilbage.
Derfor, i dette eksempel, vores omstrejfende COMMIT TRANSACTION
erklæring var faktisk nødvendig for at afslutte den implicitte transaktion.