sql >> Database >  >> RDS >> Sqlserver

Hoe te repareren "Het COMMIT TRANSACTION-verzoek heeft geen overeenkomstige BEGIN TRANSACTION" in SQL Server

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.


  1. SQL Server:Dynamische waar-clausule

  2. Het kantelpunt visualiseren met Plan Explorer

  3. 4 manieren om rijen te vinden die hoofdletters bevatten in PostgreSQL

  4. Voeg twee partities samen tot één in SQL Server (T-SQL)