Puntos de retorno de transacciones
Los puntos de retorno ofrecen un mecanismo para revertir partes de una transacción. Puede crear un punto de retorno mediante la instrucción SAVE TRANSACTION savepoint_name. Más adelante, ejecute una instrucción ROLLBACK TRANSACTION savepoint_name para revertir al punto de retorno en vez de revertir al inicio de la transacción.
Los puntos de retorno son útiles en situaciones en que no es probable que se produzcan errores. El uso de un punto de retorno para revertir parte de una transacción en caso de producirse un error no frecuente puede resultar más eficaz que hacer que cada transacción pruebe si una actualización es válida antes de realizarla. Las operaciones de actualizar y revertir son costosas, por lo que los puntos de retorno sólo son eficaces si la probabilidad de encontrar un error es baja y el costo de comprobar la validez de una actualización de antemano es relativamente alto.
En este ejemplo se muestra la utilización de un punto de retorno en un sistema de pedidos en el que hay pocas probabilidades de agotar las existencias debido a que la compañía tiene proveedores eficaces y puntos de nuevo pedido. Normalmente, una aplicación comprobaría que hay suficientes existencias antes de intentar realizar las actualizaciones que registran el pedido. Este ejemplo supone que, por algún motivo, comprobar de antemano la cantidad disponible en las existencias es relativamente costoso (debido a una conexión sobre un módem o WAN lentos). Se podría codificar la aplicación para que realizara sólo la actualización y, si se produjera un error que indicara que no hay existencias suficientes, revirtiera la actualización. En este caso, una comprobación de @@ERROR tras la inserción es más rápido que comprobar la cantidad antes de la actualización.
La tabla InvCtrl tiene una restricción CHECK que desencadena un error 547 si la columna QtyInStk tiene un valor inferior a 0. El procedimiento OrderStock crea un punto de retorno. Si se produce el error 547, revierte hasta el punto de retorno y devuelve el número de elementos disponibles al proceso que realiza la llamada. Éste puede entonces reemplazar el pedido por la cantidad disponible. Si OrderStock devuelve 0, el proceso que realiza la llamada comprueba que había suficientes existencias disponibles para satisfacer el pedido.
SET NOCOUNT OFF;
GO
USE AdventureWorks2008R2;
GO
CREATE TABLE InvCtrl
(WhrhousID int,
PartNmbr int,
QtyInStk int,
ReordrPt int,
CONSTRAINT InvPK PRIMARY KEY
(WhrhousID, PartNmbr),
CONSTRAINT QtyStkCheck CHECK (QtyInStk > 0) );
GO
CREATE PROCEDURE OrderStock
@WhrhousID int,
@PartNmbr int,
@OrderQty int
AS
DECLARE @ErrorVar int;
SAVE TRANSACTION StkOrdTrn;
UPDATE InvCtrl SET QtyInStk = QtyInStk - @OrderQty
WHERE WhrhousID = @WhrhousID
AND PartNmbr = @PartNmbr;
SELECT @ErrorVar = @@error;
IF (@ErrorVar = 547)
BEGIN
ROLLBACK TRANSACTION StkOrdTrn;
RETURN (SELECT QtyInStk
FROM InvCtrl
WHERE WhrhousID = @WhrhousID
AND PartNmbr = @PartNmbr);
END
ELSE
RETURN 0;
GO