Ejecutar un UPDATE con validación y reversión controlada
Necesitamos aumentar el precio de los productos activos de una categoría. La condición parece sencilla, pero un filtro incorrecto podría modificar más filas de las previstas y dejar el error confirmado antes de detectarlo.
Qué necesitamos distinguir
Una transacción agrupa cambios para confirmarlos con COMMIT o revertirlos con ROLLBACK como una unidad. Un bloqueo coordina el acceso concurrente y puede conservarse mientras la transacción siga abierta.
Separaremos la selección del objetivo, la modificación y la confirmación. Las filas se fijarán dentro de una transacción, se mostrará el antes y el después, y el cambio se revertirá mientras no exista una confirmación explícita.
Consulta
/*
Antes de ejecutar:
Revisa la base activa, los nombres de objetos, los parámetros y los permisos.
Adapta el ejemplo a tu modelo y pruébalo primero en un ambiente controlado.
Los cambios se revierten de forma predeterminada.
Mantén @ConfirmarCambios = 0 hasta validar el alcance.
*/
SET NOCOUNT ON;
GO
-- Consulta
DECLARE @IdCategoria SMALLINT = 1;
DECLARE @Porcentaje DECIMAL(5, 2) = 5.00;
DECLARE @MaximoFilas INT = 20;
DECLARE @ConfirmarCambios BIT = 0;
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
DECLARE @Objetivo TABLE
(
IdProducto INT PRIMARY KEY
);
INSERT INTO @Objetivo (IdProducto)
SELECT p.IdProducto
FROM dbo.Producto AS p WITH (UPDLOCK, HOLDLOCK)
WHERE p.IdCategoria = @IdCategoria
AND p.Activo = 1;
DECLARE @FilasObjetivo INT = @@ROWCOUNT;
IF @FilasObjetivo > @MaximoFilas
THROW 50001, N'El UPDATE supera el máximo de filas esperado.', 1;
SELECT
p.IdProducto,
p.Nombre,
p.Precio AS PrecioAntes
FROM dbo.Producto AS p
INNER JOIN @Objetivo AS o
ON o.IdProducto = p.IdProducto
ORDER BY p.IdProducto;
DECLARE @Cambios TABLE
(
IdProducto INT,
PrecioAntes DECIMAL(12, 2),
PrecioDespues DECIMAL(12, 2)
);
UPDATE p
SET p.Precio = ROUND
(p.Precio * (1 + @Porcentaje / 100.0), 2),
p.FechaActualizacion = SYSDATETIME()
OUTPUT
deleted.IdProducto,
deleted.Precio,
inserted.Precio
INTO @Cambios (IdProducto, PrecioAntes, PrecioDespues)
FROM dbo.Producto AS p
INNER JOIN @Objetivo AS o
ON o.IdProducto = p.IdProducto;
IF @@ROWCOUNT <> @FilasObjetivo
THROW 50002, N'Cambió el número de filas durante el UPDATE.', 1;
SELECT
c.IdProducto,
c.PrecioAntes,
c.PrecioDespues
FROM @Cambios AS c
ORDER BY c.IdProducto;
IF @ConfirmarCambios = 1
COMMIT TRANSACTION;
ELSE
ROLLBACK TRANSACTION;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
THROW;
END CATCH;
GO
Parámetros o permisos
Adapta la categoría, porcentaje y límite. @ConfirmarCambios permanece en cero para que el ejemplo revierta de forma predeterminada. Cambiarlo a uno solo tiene sentido después de revisar el objetivo, el resultado y los efectos asociados. Se requieren permisos de lectura y actualización. UPDLOCK y HOLDLOCK mantienen bloqueado el conjunto seleccionado hasta terminar la transacción; reducen cambios concurrentes, pero pueden hacer esperar a otras sesiones. Mantén la revisión corta y prueba primero fuera de producción.
Cómo leer el resultado
El primer resultado presenta las filas fijadas como objetivo. El segundo utiliza OUTPUT para comparar el precio anterior y el nuevo. El límite detiene la operación si el alcance supera lo esperado, y la segunda comprobación exige que el número actualizado coincida con el conjunto seleccionado. Si ocurre un error, TRY/CATCH, XACT_ABORT y XACT_STATE llevan la transacción a una reversión controlada. Un valor cero en @ConfirmarCambios también ejecuta ROLLBACK aun cuando todo sea válido.
Qué conclusión sí permite obtener
Permite comprobar el alcance y el efecto inmediato de una actualización dentro de una transacción controlada.
Qué conclusión todavía no permite obtener
No demuestra que el nuevo precio sea correcto para el negocio. Tampoco descarta efectos en triggers, auditorías, replicación, integraciones o procesos que lean las filas mientras permanecen bloqueadas.
Siguiente comprobación razonable
Revisa triggers y dependencias, prueba el script con datos representativos y conserva evidencia del conjunto esperado. Solo entonces decide si corresponde confirmar la misma operación en el ambiente autorizado.