Comparación de transacciones y lotes
Resulta útil comparar el comportamiento de los lotes de T-SQL, incluidos en un bloque TRY/CATCH, con el comportamiento de las transacciones.
Tenga en cuenta el código siguiente que inserta dos pedidos de cliente, lo que requiere una fila en la tabla SalesLT.SalesOrderHeader y una o varias filas de la tabla SalesLT.SalesOrderDetail . Todas las instrucciones INSERT se incluyen dentro del bloque TRY.
- Si se produce un error en la primera inserción, la ejecución pasa al bloque CATCH y no se ejecuta ningún código adicional.
- Si se produce un error en la segunda inserción, la ejecución pasa al bloque CATCH y no se ejecuta ningún código adicional. Sin embargo, la primera inserción se realizó correctamente y no se revierte, lo que deja la base de datos en un estado incoherente. Se ha insertado una fila para el pedido, pero no hay ninguna fila para el detalle del pedido.
BEGIN TRY
INSERT INTO dbo.Orders(custid, empid, orderdate)
VALUES (68, 9, '2021-07-12');
INSERT INTO dbo.Orders(custid, empid, orderdate)
VALUES (88, 3, '2021-07-15');
INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty)
VALUES (1, 2, 15.20, 20);
INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty)
VALUES (999, 77, 26.20, 15);
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
END CATCH;
Compare esto con implementar el código dentro de una transacción. El bloque TRY/CATCH todavía se usa para el control de errores, pero las instrucciones INSERT para las tablas Orders y OrderDetails se incluyen dentro de las palabras clave BEGIN TRANSACTION/COMMIT TRANSACTION. Esto garantiza que todas las declaraciones se traten como una sola transacción, que tiene éxito o falla. Una fila se escribe tanto en la tabla Orders como en la tabla OrderDetails, o bien no se inserta ninguna fila. De este modo, la base de datos nunca puede estar en un estado incoherente.
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO dbo.Orders(custid, empid, orderdate)
VALUES (68,9,'2006-07-15');
INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty)
VALUES (99, 2,15.20,20);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
ROLLBACK TRANSACTION;
END CATCH;