UPDATE con JOIN

MySQL permite combinar UPDATE con JOIN para actualizar filas de una tabla basándote en datos de otra tabla relacionada. Es una extensión de MySQL al estándar SQL y resulta extremadamente útil cuando necesitas sincronizar datos entre tablas o aplicar cambios basados en condiciones que involucran relaciones.

Sintaxis

UPDATE tabla1
JOIN tabla2 ON tabla1.columna = tabla2.columna
SET tabla1.columna = nuevo_valor
WHERE condicion;

El JOIN funciona igual que en un SELECT: puedes usar INNER JOIN, LEFT JOIN o cualquier tipo de JOIN. La diferencia es que después del JOIN usas SET para modificar columnas.

UPDATE con INNER JOIN

Aplicar un descuento del 10% a todos los productos de la categoría "Smartphones":

UPDATE productos p
JOIN categorias c ON p.categoria_id = c.id
SET p.precio = ROUND(p.precio * 0.90, 2)
WHERE c.nombre = 'Smartphones';
Query OK, 4 rows affected (0.01 sec)
Rows matched: 4  Changed: 4  Warnings: 0

Sin el JOIN, tendríamos que conocer el ID de la categoría Smartphones (6) y usarlo directamente. Con el JOIN podemos filtrar por nombre de categoría, que es más legible y robusto ante cambios en los IDs.

Para verificar:

SELECT p.nombre, p.precio
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
WHERE c.nombre = 'Smartphones';
nombreprecio
iPhone 15 Pro1169.99
Samsung Galaxy S24809.99
Google Pixel 8629.10
Xiaomi 14539.99

Actualizar una tabla con datos de otra

Copiar información de una tabla a otra. Supongamos que tienes una tabla con precios actualizados:

CREATE TABLE nuevos_precios (
    producto_id INT PRIMARY KEY,
    precio DECIMAL(10, 2)
);
 
INSERT INTO nuevos_precios VALUES
    (1, 1299.99),
    (2, 899.99),
    (3, 699.00),
    (4, 599.99);
 
UPDATE productos p
JOIN nuevos_precios np ON p.id = np.producto_id
SET p.precio = np.precio;
Query OK, 4 rows affected (0.01 sec)
Rows matched: 4  Changed: 4  Warnings: 0

Los precios de los 4 smartphones se actualizan con los valores de la tabla nuevos_precios. Este patrón es muy común cuando recibes actualizaciones de precios de un proveedor y necesitas aplicarlas en lote.

UPDATE con LEFT JOIN

El LEFT JOIN es útil cuando quieres actualizar registros que no tienen correspondencia en otra tabla. Marcar como inactivos los productos que nunca se han vendido:

UPDATE productos p
LEFT JOIN detalle_pedidos dp ON p.id = dp.producto_id
SET p.activo = FALSE
WHERE dp.id IS NULL;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3  Changed: 3  Warnings: 0

El LEFT JOIN incluye todos los productos. Los que no tienen ninguna fila en detalle_pedidos tendrán dp.id IS NULL. Esos productos (los que nunca se vendieron) se marcan como inactivos. En nuestra base de datos, son el Cargador USB-C 65W, el Sofá 3 plazas y la Estantería modular.

Para verificar:

SELECT nombre, activo
FROM productos
WHERE activo = FALSE;
nombreactivo
Cargador USB-C 65W0
Sofá 3 plazas0
Estantería modular0

Actualizar múltiples tablas

MySQL permite actualizar varias tablas en un solo UPDATE:

UPDATE pedidos p
JOIN clientes cl ON p.cliente_id = cl.id
SET p.notas = CONCAT('Cliente: ', cl.nombre, ' ', cl.apellidos),
    cl.telefono = COALESCE(cl.telefono, 'No registrado')
WHERE p.estado = 'pendiente';

Esta sentencia actualiza tanto la tabla pedidos (añadiendo el nombre del cliente en las notas) como la tabla clientes (rellenando teléfonos NULL) para los pedidos pendientes. Ambos cambios se ejecutan en una sola operación atómica.

UPDATE con JOIN y agregación

No puedes usar funciones de agregación directamente en un UPDATE JOIN, pero puedes usar una subconsulta o tabla derivada. Actualizar el total de cada pedido calculándolo desde los detalles:

UPDATE pedidos p
JOIN (
    SELECT
        pedido_id,
        SUM(cantidad * precio_unitario) AS total_calculado
    FROM detalle_pedidos
    GROUP BY pedido_id
) AS totales ON p.id = totales.pedido_id
SET p.total = totales.total_calculado;
Query OK, 25 rows affected (0.01 sec)
Rows matched: 25  Changed: 25  Warnings: 0

La tabla derivada calcula el total real de cada pedido sumando las líneas de detalle. El UPDATE aplica esos totales calculados a la tabla pedidos. Este patrón es útil para recalcular campos desnormalizados cuando se detectan inconsistencias.

UPDATE JOIN vs subconsulta correlacionada

Ambas técnicas logran lo mismo, pero el UPDATE con JOIN suele ser más eficiente y legible:

-- Con JOIN (preferido)
UPDATE productos p
JOIN categorias c ON p.categoria_id = c.id
SET p.precio = p.precio * 0.95
WHERE c.nombre = 'Portátiles';
 
-- Con subconsulta (alternativa)
UPDATE productos
SET precio = precio * 0.95
WHERE categoria_id = (
    SELECT id FROM categorias WHERE nombre = 'Portátiles'
);

Ambas aplican un 5% de descuento a los portátiles. La versión con JOIN es más versátil: permite acceder a columnas de la tabla unida en el SET, no solo en el WHERE.

Limpiar

DROP TABLE IF EXISTS nuevos_precios;
 
-- Restaurar productos inactivos
UPDATE productos SET activo = TRUE WHERE activo = FALSE;

En el siguiente artículo veremos la sentencia DELETE para eliminar filas de una tabla.

Escrito por Eduardo Lázaro