Comparación de transacciones y lotes

Completado

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;