Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да коригирате „Заявката COMMIT TRANSACTION няма съответна BEGIN TRANSACTION“ в SQL Server

Ако получавате съобщение за грешка Msg 3902, ниво 16, което гласи „Заявката COMMIT TRANSACTION няма съответна BEGIN TRANSACTION“, това вероятно е защото имате бездомен COMMIT изявление.

Може да получите това поради внедряване на обработка на грешки и забравяне, че вече сте ангажирали или отменили транзакцията другаде в кода си.

Пример за грешка

Ето един прост пример за демонстриране на грешката:

SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;

Резултат:

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

Това ще се случи, ако SET IMPLICIT_TRANSACTIONS е OFF . Вижте по-долу какво се случва, когато SET IMPLICIT_TRANSACTIONS е ON .

Пример за грешка поради обработка на грешки

Може да получите това поради внедряване на обработка на грешки и забравяне, че вече сте ангажирали или отменили транзакцията другаде в кода си.

Например:

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;

Резултат:

(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.

В този случай вече имах COMMIT TRANSACTION в TRY блок. Така че до момента на втората COMMIT TRANSACTION е бил открит, транзакцията вече е била извършена.

Ще видим същото, дори ако транзакцията е срещнала грешка и е била отменена. Отмяната ще прекрати транзакцията и следователно няма повече COMMIT са необходими изявления.

Така че, за да коригираме този проблем, просто ще премахнем последната COMMIT TRANSACTION , а кодът на транзакцията ще изглежда така:

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

Неявни транзакции

Ако имате активирани неявни транзакции, може да получите различни резултати от първия пример.

Ако зададем IMPLICIT_TRANSACTIONS до ON , ето какво получаваме:

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

Резултат:

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

Не се появява грешка.

Това е така, защото определени T-SQL оператори автоматично стартират транзакция, когато се изпълняват. Сякаш са предшествани от невидима BEGIN TRANSACTION изявление.

Когато IMPLICIT_TRANSACTIONS е OFF , тези изявления се ангажират автоматично. Сякаш са последвани от невидима COMMIT TRANSACTION изявление. В този сценарий транзакцията е в режим на автоматично извършване.

Когато IMPLICIT_TRANSACTIONS е ON , няма невидима COMMIT TRANSACTION изявление. Тези оператори все още се стартират от невидима BEGIN TRANSACTION , но те трябва да бъдат завършени изрично.

Неявната транзакция остава в ход, докато не бъде изрично ангажирана или изрично връщана назад.

Следователно, в този пример, нашата бездомна COMMIT TRANSACTION изявлението всъщност беше необходимо за прекратяване на имплицитната транзакция.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да използвате функциите на SQL Server AlwaysOn

  2. Какво е скаларен UDF в SQL Server?

  3. Какъв е най-добрият начин за групови вмъквания в база данни от C#?

  4. Параметризираната заявка ..... очаква параметъра '@units', който не беше предоставен

  5. Променливи, чувствителни към малки и големи букви в SQL Server