sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man åtgärdar "Begäran COMMIT TRANSACTION har ingen motsvarande BEGIN TRANSACTION" i SQL Server

Om du får felmeddelande 3902, nivå 16, som lyder "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION", beror det förmodligen på att du har en bortkommen COMMIT uttalande.

Du kan få detta på grund av att du implementerar felhantering och glömmer att du redan har genomfört eller återställt transaktionen någon annanstans i din kod.

Exempel på fel

Här är ett enkelt exempel för att visa felet:

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.

Detta inträffar om din SET IMPLICIT_TRANSACTIONS är OFF . Se nedan för vad som händer när SET IMPLICIT_TRANSACTIONS är ON .

Exempel på fel på grund av felhantering

Du kan få detta på grund av att du implementerar felhantering och glömmer att du redan har genomfört eller återställt transaktionen någon annanstans i din kod.

Till exempel:

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 det här fallet hade jag redan COMMIT TRANSACTION i TRY blockera. Så när den andra COMMIT TRANSACTION påträffades, hade transaktionen redan genomförts.

Vi skulle se detsamma även om transaktionen hade stött på ett fel och återställts. En återställning kommer att avsluta transaktionen och därför ingen ytterligare COMMIT uttalanden krävs.

Så för att åtgärda det här problemet skulle vi helt enkelt ta bort den sista COMMIT TRANSACTION , och transaktionskoden skulle se ut så här:

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

Implicita transaktioner

Om du har aktiverat implicita transaktioner kan du få andra resultat än det första exemplet.

Om vi ​​ställer in IMPLICIT_TRANSACTIONS till ON , här är vad 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)

Inget fel uppstår.

Detta beror på att vissa T-SQL-satser automatiskt startar en transaktion när de körs. Det är som om de föregåtts av en osynlig BEGIN TRANSACTION uttalande.

När IMPLICIT_TRANSACTIONS är OFF , dessa uttalanden begås automatiskt. Det är som om de efterträds av en osynlig COMMIT TRANSACTION påstående. I det här scenariot är transaktionen i autocommit-läge.

När IMPLICIT_TRANSACTIONS är ON , det finns ingen osynlig COMMIT TRANSACTION påstående. Dessa uttalanden startas fortfarande av en osynlig BEGIN TRANSACTION , men de måste avslutas explicit.

En implicit transaktion förblir pågående tills den antingen explicit begåtts eller explicit återställs.

Därför, i det här exemplet, vår herrelösa COMMIT TRANSACTION uttalande behövdes faktiskt för att avsluta den implicita transaktionen.


  1. Hur NULLIF() fungerar i SQL Server

  2. Prestandaöverväganden för temporär data i Oracle

  3. pgadmin4 :postgresql applikationsserver kunde inte kontaktas.

  4. Hur jämför man data mellan två databaser i PostgreSQL?