La sentencia UPDATE sirve para actualizar valores de una o varias filas en una tabla. Puedes cambiar uno o varios campos a la vez y limitar qué filas se modifican mediante WHERE. También podés usar subconsultas (SUBQUERY), JOIN, CTE (WITH) y, según el motor, devolver filas afectadas.
👉 Idea central: UPDATE cambia el estado de tus datos. Con gran poder viene gran responsabilidad: sin WHERE actualizás toda la tabla.
Sintaxis básica de UPDATE
UPDATE nombre_tabla
SET columna1 = valor1,
columna2 = valor2,
...
[WHERE condición];
SET: lista de asignacionescolumna = expresión.WHERE(opcional pero casi siempre necesario): filtra qué filas actualizar.- Si omitís
WHERE, todas las filas de la tabla serán modificadas.
Ejemplo básico
UPDATE empleados
SET salario = salario * 1.05
WHERE departamento = 'Ventas';
👉 Aumenta 5% el salario de empleados en Ventas.
Actualizar múltiples columnas y usar expresiones
Podés calcular con funciones o subconsultas:
UPDATE productos
SET precio = precio * 0.9,
actualizado_en = NOW()
WHERE categoria = 'Outlet';
Con subconsulta (ej. ajustar precio al promedio de su categoría):
UPDATE productos p
SET precio = (
SELECT AVG(precio)
FROM productos
WHERE categoria = p.categoria
)
WHERE p.categoria IN ('Audio','Video');
UPDATE con JOIN (según motor)
Cuando necesitás tomar datos de otra tabla para calcular el nuevo valor.
MySQL / MariaDB
UPDATE pedidos p
JOIN clientes c ON c.id = p.cliente_id
SET p.descuento = 0.1
WHERE c.segmento = 'Premium';
PostgreSQL (usando FROM)
UPDATE pedidos p
SET descuento = 0.1
FROM clientes c
WHERE c.id = p.cliente_id
AND c.segmento = 'Premium';
SQL Server
UPDATE p
SET p.descuento = 0.1
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id
WHERE c.segmento = 'Premium';
UPDATE con CTE (Common Table Expressions)
Los CTE ayudan a hacer el código más legible y a reutilizar lógicas.
WITH top_clientes AS (
SELECT cliente_id
FROM pedidos
GROUP BY cliente_id
HAVING SUM(total) > 5000
)
UPDATE clientes c
SET nivel = 'Oro'
FROM top_clientes t
WHERE c.id = t.cliente_id;
(Sintaxis típica de PostgreSQL/SQL Server.)
UPDATE con funciones de ventana (vía subconsulta)
Algunos motores permiten combinar lógicas de ranking dentro de una subconsulta:
UPDATE empleados e
SET rango_sal = sub.rnk
FROM (
SELECT id,
DENSE_RANK() OVER (ORDER BY salario DESC) AS rnk
FROM empleados
) sub
WHERE e.id = sub.id;
Devolver filas afectadas (RETURNING / OUTPUT)
- PostgreSQL y SQLite (3.35+):
RETURNING - SQL Server:
OUTPUT
-- PostgreSQL / SQLite
UPDATE empleados
SET salario = salario * 1.1
WHERE id IN (10,11)
RETURNING id, salario;
-- SQL Server
UPDATE empleados
SET salario = salario * 1.1
OUTPUT inserted.id, inserted.salario
WHERE id IN (10,11);
👉 Ideal para APIs: actualizás y obtenés el nuevo estado en una sola operación.
Control transaccional (COMMIT / ROLLBACK)
Para operaciones críticas o masivas, usá transacciones:
BEGIN;
UPDATE cuentas SET saldo = saldo - 100 WHERE id = 1;
UPDATE cuentas SET saldo = saldo + 100 WHERE id = 2;
-- Validaciones...
-- COMMIT si todo ok
COMMIT;
-- o ROLLBACK si algo falló
-- ROLLBACK;
Ejemplos prácticos
1) Normalizar emails a minúsculas
UPDATE usuarios
SET email = LOWER(email)
WHERE email <> LOWER(email);
2) Cerrar pedidos antiguos sin pago
UPDATE pedidos
SET estado = 'CANCELADO'
WHERE estado = 'PENDIENTE'
AND fecha < CURRENT_DATE - INTERVAL '30 days';
(Ajustar sintaxis de intervalo según motor.)
3) Reasignar categoría por total consumido
WITH gasto AS (
SELECT cliente_id, SUM(total) total
FROM pedidos
GROUP BY cliente_id
)
UPDATE clientes c
SET categoria = CASE
WHEN g.total >= 5000 THEN 'Oro'
WHEN g.total >= 2000 THEN 'Plata'
ELSE 'Bronce'
END
FROM gasto g
WHERE c.id = g.cliente_id;
Rendimiento y concurrencia
- Índices: asegurá índices en columnas usadas en
WHERE/JOIN. - Bloqueos: un
UPDATEbloquea filas; en cargas altas, preferí batching (actualizar en bloques). - Estadísticas actualizadas: ayudan al optimizador a elegir buenos planes.
- Evitar funciones en columnas de filtro (p. ej.
WHERE LOWER(email) = '...') porque pueden impedir uso de índices (salvo índices funcionales).
Errores comunes con UPDATE
- Olvidar
WHERE- Actualizás TODA la tabla. Usá transacciones y probá primero con un
SELECT.
- Actualizás TODA la tabla. Usá transacciones y probá primero con un
- Falta de condición única
- Un
JOINmal definido puede actualizar muchas filas inesperadas.
- Un
- Subconsulta que devuelve múltiples filas
SET col = (SELECT ... ) -- si retorna >1 fila, error. - Dependencia circular
- Actualizar una columna usando otra que acaba de ser modificada puede dar resultados no deseados.
- Triggers “sorpresa”
- Un
UPDATEpuede disparar triggers que cambian más cosas; revisá qué triggers existen.
- Un
- Conversión de tipos
- Asignar texto a una columna numérica o viceversa provoca errores o truncamientos.
Buenas prácticas con UPDATE
- Siempre comenzá con un
SELECTde verificación usando el mismoWHERE/JOIN. - Ejecutá cambios en transacciones para poder revertir.
- Logueá cuántas filas se afectaron (conteo de filas modificadas).
- Para actualizaciones masivas, considerá procesos por lotes y horarios de baja carga.
- Documentá el propósito del
UPDATE(comentarios en SQL o ticket de cambio). - Donde corresponda, usá
RETURNING/OUTPUTpara confirmar el resultado.
Variantes por motor de base de datos
- MySQL / MariaDB
UPDATE ... JOIN ...es muy común.LIMITenUPDATEpara acotar lotes:UPDATE logs SET archivado = 1 WHERE archivado = 0 LIMIT 1000;
- PostgreSQL
UPDATE ... FROM ...para “join-like updates”.RETURNINGpara devolver filas modificadas.- Funciones ricas de fecha/hora y CTE recursivos.
- SQL Server
UPDATEconFROMyJOIN.OUTPUT inserted.* / deleted.*para auditar cambios.TOP (n)para lotes:UPDATE TOP (1000) logs SET archivado = 1 WHERE archivado = 0;
- Oracle
UPDATEcon subqueries correlacionadas.MERGEpara upserts (alternativa si necesitás insertar cuando no existe).
- SQLite
- Soporta
RETURNING(3.35+). - Join updates típicamente via subqueries.
- Soporta
UPDATE vs MERGE vs UPSERT
- UPDATE: modifica filas existentes.
- MERGE: según condición, hace
UPDATEoINSERT(y a vecesDELETE). - UPSERT (depende del motor): “insert o actualizá si ya existe”.
- MySQL:
INSERT ... ON DUPLICATE KEY UPDATE - PostgreSQL:
INSERT ... ON CONFLICT (...) DO UPDATE
- MySQL:
Si tu caso requiere crear filas inexistentes, evaluá MERGE/UPSERT en lugar de UPDATE puro.
Auditoría y seguimiento
Para rastrear cambios:
- Timestamps: columnas
updated_atconDEFAULT/triggers. - Triggers: guardan histórico en tablas de auditoría.
- OUTPUT/RETURNING: registrar qué se cambió en logs de app.
Ejemplo (PostgreSQL):
CREATE TRIGGER usuarios_touch
BEFORE UPDATE ON usuarios
FOR EACH ROW
EXECUTE FUNCTION set_updated_at();
Preguntas frecuentes (FAQ)
1) ¿Qué pasa si no pongo WHERE?
Se actualizan todas las filas. Usá transacciones y un SELECT previo de control.
2) ¿Puedo actualizar usando datos de otra tabla?
Sí, con JOIN/FROM (según motor) o subconsultas.
3) ¿Cómo sé cuántas filas cambié?
La mayoría de motores devuelven el rowcount. También podés usar RETURNING/OUTPUT.
4) ¿Puedo actualizar y ver el nuevo valor en la misma consulta?
Sí: RETURNING (PostgreSQL/SQLite) u OUTPUT (SQL Server).
5) ¿UPDATE es transaccional?
Sí. En motores transaccionales, podés COMMIT/ROLLBACK.
Conclusión
UPDATE es la herramienta esencial para mantener tus datos al día:
- Permite modificar una o muchas filas con precisión usando
WHERE. - Se potencia con
JOIN, CTE y subconsultas. - Con transacciones,
RETURNING/OUTPUTy buenas prácticas, podés actualizar de forma segura y auditada.
Dominar UPDATE te da control real sobre la calidad y consistencia de tu base de datos.
Practica actualizaciones seguras en INSERT, UPDATE y DELETE y repasa el Glosario SQL completo.