Si recibe el mensaje de error 3902, nivel 16, que dice "La solicitud COMMIT TRANSACTION no tiene BEGIN TRANSACTION correspondiente", probablemente se deba a que tiene un COMMIT
perdido. declaración.
Podría estar obteniendo esto debido a la implementación del manejo de errores y al olvido de que ya comprometió o revirtió la transacción en otra parte de su código.
Ejemplo de error
Aquí hay un ejemplo simple para demostrar el error:
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.
Esto ocurrirá si su SET IMPLICIT_TRANSACTIONS
está OFF
. Vea a continuación lo que sucede cuando SET IMPLICIT_TRANSACTIONS
está ON
.
Ejemplo de error debido a la gestión de errores
Podría estar obteniendo esto debido a la implementación del manejo de errores y al olvido de que ya comprometió o revirtió la transacción en otra parte de su código.
Por ejemplo:
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.
En este caso, ya tenía COMMIT TRANSACTION
en el TRY
cuadra. Entonces, para cuando el segundo COMMIT TRANSACTION
se encontró, la transacción ya se había confirmado.
Veríamos lo mismo incluso si la transacción hubiera encontrado un error y se revirtiera. Una reversión finalizará la transacción y, por lo tanto, no más COMMIT
se requieren declaraciones.
Entonces, para solucionar este problema, simplemente eliminaríamos la última COMMIT TRANSACTION
, y el código de transacción se vería así:
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
Transacciones implícitas
Si tiene habilitadas las transacciones implícitas, es posible que obtenga resultados diferentes a los del primer ejemplo.
Si configuramos IMPLICIT_TRANSACTIONS
a ON
, esto es lo que obtenemos:
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)
No se produce ningún error.
Esto se debe a que ciertas declaraciones de T-SQL inician automáticamente una transacción cuando se ejecutan. Es como si estuvieran precedidos por un BEGIN TRANSACTION
invisible declaración.
Cuando IMPLICIT_TRANSACTIONS
está OFF
, estas sentencias se confirman automáticamente. Es como si les sucediera una COMMIT TRANSACTION
invisible. declaración. En este escenario, la transacción está en modo de confirmación automática.
Cuando IMPLICIT_TRANSACTIONS
está ON
, no hay COMMIT TRANSACTION
invisible declaración. Estas declaraciones aún se inician con un BEGIN TRANSACTION
invisible , pero deben finalizarse explícitamente.
Una transacción implícita permanece en curso hasta que se confirma explícitamente o se revierte explícitamente.
Por lo tanto, en este ejemplo, nuestro COMMIT TRANSACTION
perdido la declaración era realmente necesaria para finalizar la transacción implícita.