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';| nombre | precio |
|---|---|
| iPhone 15 Pro | 1169.99 |
| Samsung Galaxy S24 | 809.99 |
| Google Pixel 8 | 629.10 |
| Xiaomi 14 | 539.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;| nombre | activo |
|---|---|
| Cargador USB-C 65W | 0 |
| Sofá 3 plazas | 0 |
| Estantería modular | 0 |
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
