Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

So beheben Sie „Die COMMIT TRANSACTION-Anforderung hat keine entsprechende BEGIN TRANSACTION“ in SQL Server

Wenn Sie die Fehlermeldung 3902, Ebene 16 erhalten, die lautet:„Die Anfrage COMMIT TRANSACTION hat keine entsprechende BEGIN TRANSACTION“, liegt das wahrscheinlich daran, dass Sie einen verirrten COMMIT haben Erklärung.

Sie könnten dies erhalten, weil Sie die Fehlerbehandlung implementieren und vergessen, dass Sie die Transaktion bereits an anderer Stelle in Ihrem Code festgeschrieben oder rückgängig gemacht haben.

Fehlerbeispiel

Hier ist ein einfaches Beispiel, um den Fehler zu demonstrieren:

SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;

Ergebnis:

(7 rows affected)
Msg 3902, Level 16, State 1, Line 2
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

Dies geschieht, wenn Sie SET IMPLICIT_TRANSACTIONS ist OFF . Unten erfahren Sie, was passiert, wenn SET IMPLICIT_TRANSACTIONS ist ON .

Beispiel für Fehler aufgrund von Fehlerbehandlung

Sie könnten dies erhalten, weil Sie die Fehlerbehandlung implementieren und vergessen, dass Sie die Transaktion bereits an anderer Stelle in Ihrem Code festgeschrieben oder rückgängig gemacht haben.

Zum Beispiel:

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;

Ergebnis:

(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 diesem Fall hatte ich bereits COMMIT TRANSACTION im TRY Block. Also bis zum zweiten COMMIT TRANSACTION gefunden wurde, wurde die Transaktion bereits festgeschrieben.

Wir würden dasselbe sehen, selbst wenn die Transaktion auf einen Fehler gestoßen wäre und zurückgesetzt wurde. Ein Rollback beendet die Transaktion und daher kein weiteres COMMIT Angaben sind erforderlich.

Um dieses Problem zu beheben, entfernen wir einfach die letzte COMMIT TRANSACTION , und der Transaktionscode würde wie folgt aussehen:

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

Implizite Transaktionen

Wenn Sie implizite Transaktionen aktiviert haben, erhalten Sie möglicherweise andere Ergebnisse als im ersten Beispiel.

Wenn wir IMPLICIT_TRANSACTIONS setzen auf ON , hier ist, was wir bekommen:

SET IMPLICIT_TRANSACTIONS ON;
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;

Ergebnis:

+---------------------------------+----------------+
| 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)

Es tritt kein Fehler auf.

Dies liegt daran, dass bestimmte T-SQL-Anweisungen automatisch eine Transaktion starten, wenn sie ausgeführt werden. Es ist, als ob ihnen ein unsichtbares BEGIN TRANSACTION vorangestellt wäre Erklärung.

Wenn IMPLICIT_TRANSACTIONS ist OFF , werden diese Anweisungen automatisch festgeschrieben. Es ist, als würde ihnen eine unsichtbare COMMIT TRANSACTION folgen Erklärung. In diesem Szenario befindet sich die Transaktion im Autocommit-Modus.

Wenn IMPLICIT_TRANSACTIONS ist ON , gibt es keine unsichtbare COMMIT TRANSACTION Erklärung. Diese Anweisungen werden immer noch durch ein unsichtbares BEGIN TRANSACTION gestartet , aber sie müssen explizit beendet werden.

Eine implizite Transaktion bleibt in Bearbeitung, bis sie entweder explizit festgeschrieben oder explizit zurückgesetzt wird.

Daher in diesem Beispiel unser Streuner COMMIT TRANSACTION -Anweisung wurde tatsächlich benötigt, um die implizite Transaktion zu beenden.