UPDATE: modificar únicamente las filas previstas
Actualizar datos parece sencillo hasta que una condición afecta más filas de las esperadas. La parte esencial de un UPDATE no es la asignación, sino demostrar antes cuáles filas cambiarán y comprobar después el resultado.
La idea
UPDATE modifica una o varias columnas en las filas que cumplen WHERE. Si omitimos el filtro, todas las filas de la tabla quedan dentro del alcance.
Sintaxis
UPDATE dbo.Tabla
SET
Columna1 = NuevoValor,
Columna2 = OtraExpresion
WHERE Condicion;
Ejemplo: revisar antes de actualizar
Queremos aumentar 5% el precio de los productos activos de una categoría. Primero observamos el estado actual y calculamos el nuevo valor:
ROUND(valor, 2) redondea el cálculo a dos posiciones decimales. La función recibe primero el valor que debe ajustar y después la cantidad de decimales que conservará.
DECLARE @IdCategoria SMALLINT = 1;
DECLARE @Factor DECIMAL(6, 4) = 1.05;
SELECT
p.IdProducto,
p.Nombre,
p.Precio AS PrecioActual,
ROUND(p.Precio * @Factor, 2) AS PrecioNuevo
FROM dbo.Producto AS p
WHERE p.IdCategoria = @IdCategoria
AND p.Activo = 1;
Las primeras líneas crean variables con DECLARE, construcción explicada en DECLARE, SET y SELECT.
Después reutilizamos exactamente la misma condición:
SYSDATETIME() obtiene la fecha y hora actuales del servidor. @@ROWCOUNT conserva el número de filas afectadas por la instrucción inmediatamente anterior; por eso se consulta justo después del UPDATE.
UPDATE p
SET
p.Precio = ROUND(p.Precio * @Factor, 2),
p.FechaActualizacion = SYSDATETIME()
FROM dbo.Producto AS p
WHERE p.IdCategoria = @IdCategoria
AND p.Activo = 1;
SELECT @@ROWCOUNT AS FilasActualizadas;
Otra instrucción entre el UPDATE y la lectura de @@ROWCOUNT podría reemplazar ese número.
Actualizar mediante una unión
Cuando el nuevo valor depende de otra tabla podemos utilizar UPDATE ... FROM:
UPDATE p
SET p.Activo = 0
FROM dbo.Producto AS p
INNER JOIN dbo.Categoria AS c
ON c.IdCategoria = p.IdCategoria
WHERE c.Nombre = N'Almacenamiento'
AND p.Existencia = 0;
La unión debe producir una relación inequívoca para cada fila que se actualizará. Si una fila del destino coincide con varias filas de origen, el resultado puede no ser determinista: la consulta no define cuál coincidencia debe prevalecer y una ejecución futura podría elegir otra.
Validar con una transacción
En una corrección manual podemos mantener la decisión de confirmar separada de la ejecución. Una transacción agrupa cambios que después podemos confirmar con COMMIT o revertir con ROLLBACK:
BEGIN TRANSACTION;
UPDATE dbo.Producto
SET Activo = 0
WHERE IdProducto = 6;
SELECT
IdProducto,
Nombre,
Activo
FROM dbo.Producto
WHERE IdProducto = 6;
-- Sustituir por COMMIT solo después de validar el resultado.
ROLLBACK;
Una transacción abierta conserva bloqueos —protecciones que coordinan el acceso concurrente a los datos— y utiliza recursos. No debe dejarse esperando indefinidamente mientras se realiza la revisión.
Qué conviene comprobar
Además del número de filas, revisamos los valores anteriores, los nuevos, las restricciones y los efectos indirectos de triggers. Un trigger es código que SQL Server ejecuta automáticamente ante operaciones definidas sobre una tabla. También confirmamos que el filtro utilice tipos compatibles y que no dependa de una comparación ambigua con NULL, la marca de un valor ausente o desconocido.
En operaciones repetibles conviene evitar actualizaciones innecesarias, por ejemplo agregando una condición que descarte filas cuyo valor ya sea el esperado.