Se você está recebendo o erro Msg 3902, Level 16, que diz "A solicitação COMMIT TRANSACTION não tem BEGIN TRANSACTION correspondente", provavelmente é porque você tem um
COMMIT
perdido demonstração. Você pode estar recebendo isso devido à implementação do tratamento de erros e esquecendo que já confirmou ou reverteu a transação em outro lugar do seu código.
Exemplo de erro
Aqui está um exemplo simples para demonstrar o erro:
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Resultado:
(7 rows affected) Msg 3902, Level 16, State 1, Line 2 The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Isso ocorrerá se o seu
SET IMPLICIT_TRANSACTIONS
está OFF
. Veja abaixo o que acontece quando SET IMPLICIT_TRANSACTIONS
está ON
. Exemplo de erro devido ao tratamento de erros
Você pode estar recebendo isso devido à implementação do tratamento de erros e esquecendo que já confirmou ou reverteu a transação em outro lugar do seu código.
Por exemplo:
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;
Resultado:
(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.
Nesse caso, eu já tinha
COMMIT TRANSACTION
no TRY
quadra. Então, quando o segundo COMMIT TRANSACTION
foi encontrado, a transação já havia sido confirmada. Veríamos o mesmo mesmo que a transação encontrasse um erro e fosse revertida. Uma reversão encerrará a transação e, portanto, não haverá mais
COMMIT
declarações são necessárias. Então, para corrigir esse problema, simplesmente removemos o último
COMMIT TRANSACTION
, e o código da transação ficaria assim: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
Transações Implícitas
Se você tiver transações implícitas habilitadas, poderá obter resultados diferentes do primeiro exemplo.
Se definirmos
IMPLICIT_TRANSACTIONS
para ON
, eis o que obtemos:SET IMPLICIT_TRANSACTIONS ON;
SELECT ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
Resultado:
+---------------------------------+----------------+ | 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)
Nenhum erro ocorre.
Isso ocorre porque certas instruções T-SQL iniciam automaticamente uma transação quando são executadas. É como se eles fossem precedidos por um
BEGIN TRANSACTION
invisível demonstração. Quando
IMPLICIT_TRANSACTIONS
está OFF
, essas instruções são confirmadas automaticamente. É como se eles fossem sucedidos por um invisível COMMIT TRANSACTION
demonstração. Nesse cenário, a transação está no modo de confirmação automática. Quando
IMPLICIT_TRANSACTIONS
está ON
, não há COMMIT TRANSACTION
invisível demonstração. Essas instruções ainda são iniciadas por um BEGIN TRANSACTION
invisível , mas eles precisam ser encerrados explicitamente. Uma transação implícita permanece em andamento até que seja explicitamente confirmada ou explicitamente revertida.
Portanto, neste exemplo, nosso
COMMIT TRANSACTION
perdido foi realmente necessária para encerrar a transação implícita.