sql >> Database teknologi >  >> RDS >> Sqlserver

Sådan rettes "COMMIT TRANSACTION-anmodningen har ingen tilsvarende BEGIN TRANSACTION" i SQL Server

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.


  1. Tjek den plads, der bruges af en tabel i SQL Server

  2. Hvordan gendanner man data fra en slettet Docker-container? Hvordan forbindes den til dataene igen?

  3. Gendannelse af en databasesikkerhedskopi i OpenCart 1.5

  4. Sådan fungerer MAKEDATE() i MariaDB