UPDATE en SQL: qué es, cómo funciona y ejemplos prácticos

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 asignaciones columna = 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 UPDATE bloquea 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

  1. Olvidar WHERE
    • Actualizás TODA la tabla. Usá transacciones y probá primero con un SELECT.
  2. Falta de condición única
    • Un JOIN mal definido puede actualizar muchas filas inesperadas.
  3. Subconsulta que devuelve múltiples filas SET col = (SELECT ... ) -- si retorna >1 fila, error.
  4. Dependencia circular
    • Actualizar una columna usando otra que acaba de ser modificada puede dar resultados no deseados.
  5. Triggers “sorpresa”
    • Un UPDATE puede disparar triggers que cambian más cosas; revisá qué triggers existen.
  6. 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 SELECT de verificación usando el mismo WHERE/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/OUTPUT para confirmar el resultado.

Variantes por motor de base de datos

  • MySQL / MariaDB
    • UPDATE ... JOIN ... es muy común.
    • LIMIT en UPDATE para acotar lotes: UPDATE logs SET archivado = 1 WHERE archivado = 0 LIMIT 1000;
  • PostgreSQL
    • UPDATE ... FROM ... para “join-like updates”.
    • RETURNING para devolver filas modificadas.
    • Funciones ricas de fecha/hora y CTE recursivos.
  • SQL Server
    • UPDATE con FROM y JOIN.
    • OUTPUT inserted.* / deleted.* para auditar cambios.
    • TOP (n) para lotes: UPDATE TOP (1000) logs SET archivado = 1 WHERE archivado = 0;
  • Oracle
    • UPDATE con subqueries correlacionadas.
    • MERGE para upserts (alternativa si necesitás insertar cuando no existe).
  • SQLite
    • Soporta RETURNING (3.35+).
    • Join updates típicamente via subqueries.

UPDATE vs MERGE vs UPSERT

  • UPDATE: modifica filas existentes.
  • MERGE: según condición, hace UPDATE o INSERT (y a veces DELETE).
  • UPSERT (depende del motor): “insert o actualizá si ya existe”.
    • MySQL: INSERT ... ON DUPLICATE KEY UPDATE
    • PostgreSQL: INSERT ... ON CONFLICT (...) DO UPDATE

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_at con DEFAULT/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/OUTPUT y 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.

Scroll al inicio