Actualizar datos: la sentencia UPDATE

Los datos que se añaden no siempre siguen siendo correctos: la gente se cambia de apellido, en los pagos aparecen erratas y hay que recalcular precios. Para corregir una fila sin borrarla se usa la sentencia UPDATE.

Estructura general de una consulta con UPDATE

MySQL 8.4
UPDATE nombre_tabla
SET campo_tabla = valor [, ...]
[WHERE condicion_seleccion];
  • [ ]parte opcional
  • ...se puede repetir
nombre_tabla
La tabla en la que se modifican los registros.
campo_tabla

La columna a la que se asigna un valor nuevo. Puede haber varios pares campo_tabla = valor separados por comas.

valor

El valor nuevo: un número, una cadena, una expresión como price * 1.1 o NULL.

condicion_seleccion

Qué filas modificar. Sin WHERE se modifican todas las filas de la tabla.

Opcional

Por ejemplo, Andie (Andie Quincey) se ha cambiado el apellido: ahora es Andie Anthony.

MySQL 8.4
UPDATE FamilyMembers
SET member_name = 'Andie Anthony'
WHERE member_name = 'Andie Quincey';
member_idstatusmember_namebirthday
1fatherHeadley Quincey1960-05-13T00:00:00.000Z
2motherFlavia Quincey1963-02-16T00:00:00.000Z
3sonAndie QuinceyAndie Anthony1983-06-05T00:00:00.000Z
4daughterLela Quincey1985-06-07T00:00:00.000Z
5
4 filas más
daughterAnnie Quincey1988-04-10T00:00:00.000Z

Modificar varias columnas

Para modificar varias columnas a la vez, enumera después de SET los pares campo_tabla = valor separados por comas. Por ejemplo, Andie compró 4 envases de leche a 25 cada uno, pero en el pago con identificador 3 se registraron por error 5 a 20. Corrijamos las dos columnas con una sola consulta:

MySQL 8.4
UPDATE Payments
SET amount = 4, unit_price = 25
WHERE payment_id = 3;
payment_iddatefamily_membergoodamountunit_price
12005-02-12T00:00:00.000Z1112000
22005-03-23T00:00:00.000Z2112100
32005-05-14T00:00:00.000Z34542025
42005-07-22T00:00:00.000Z451350
5
24 filas más
2005-07-26T00:00:00.000Z472150

Todas las columnas enumeradas cambian en las mismas filas: las que cumplen la condición de WHERE.

Valores calculados

El valor nuevo se puede calcular a partir del anterior; por ejemplo, para duplicar todos los precios:

MySQL 8.4
UPDATE Payments
SET unit_price = unit_price * 2;

En la expresión también puedes usar otras columnas de la misma fila, siempre que sus tipos sean compatibles. Por ejemplo, vamos a registrar el pago con identificador 3 como una sola unidad: en unit_price quedará el importe de toda la compra y en amount, el valor 1.

MySQL 8.4
UPDATE Payments
SET unit_price = unit_price * amount,
    amount = 1
WHERE payment_id = 3;

En un UPDATE sobre una sola tabla, las asignaciones de SET se ejecutan de izquierda a derecha, y la siguiente expresión ya ve el valor nuevo de la columna. Si cambias el orden de las asignaciones, unit_price se multiplicará por el 1 que ya se ha escrito en amount y no cambiará:

MySQL 8.4
UPDATE Payments
SET amount = 1,
    unit_price = unit_price * amount
WHERE payment_id = 3;

Por eso, la columna que interviene en el cálculo de otras debes modificarla la última.

Todas las expresiones de SET se calculan con los valores que tenía la fila antes del cambio, así que el orden de las asignaciones da igual. Esta consulta dará el mismo resultado:

MySQL 8.4
UPDATE Payments
SET amount = 1,
    unit_price = unit_price * amount
WHERE payment_id = 3;

Actualizar según los datos de otra tabla

A veces las filas que hay que actualizar se eligen según los datos de otra tabla. Por ejemplo, resulta que en todos los pagos de caviar el precio registrado es la mitad del real. La forma más sencilla es usar una subconsulta en WHERE:

MySQL 8.4
UPDATE Payments
SET unit_price = unit_price * 2
WHERE good IN (
    SELECT good_id
    FROM Goods
    WHERE good_name LIKE '%caviar%'
);

Lo mismo se puede conseguir combinando las tablas con JOIN directamente en la consulta UPDATE:

MySQL 8.4
UPDATE nombre_tabla_1
JOIN nombre_tabla_2 ON condicion_combinacion
SET nombre_tabla_1.campo_tabla = valor [, ...]
[WHERE condicion_seleccion];
  • [ ]parte opcional
  • ...se puede repetir
nombre_tabla_1
La tabla en la que se modifican los registros.
nombre_tabla_2

La tabla que se combina y según cuyos datos se seleccionan las filas y se calculan los valores nuevos.

condicion_combinacion

Cómo se relacionan las filas de las dos tablas, por ejemplo nombre_tabla_1.campo = nombre_tabla_2.campo.

condicion_seleccion

Qué filas modificar. En la condición se pueden comprobar columnas de ambas tablas.

Opcional
MySQL 8.4
UPDATE Payments
JOIN Goods ON Payments.good = Goods.good_id
SET Payments.unit_price = Payments.unit_price * 2
WHERE Goods.good_name LIKE '%caviar%';

Lo mismo se puede conseguir enumerando las tablas adicionales después de FROM:

MySQL 8.4
UPDATE nombre_tabla_1
SET campo_tabla = valor [, ...]
FROM nombre_tabla_2
WHERE condicion_combinacion
[AND condicion_seleccion];
  • [ ]parte opcional
  • ...se puede repetir
nombre_tabla_1

La tabla en la que se modifican los registros. No hace falta repetirla después de FROM.

campo_tabla

Una columna de la tabla nombre_tabla_1. Delante de ella no se indica el nombre de la tabla.

nombre_tabla_2

Una tabla adicional según cuyos datos se seleccionan las filas y se calculan los valores nuevos.

condicion_combinacion

Cómo se relacionan las filas de las dos tablas, por ejemplo nombre_tabla_1.campo = nombre_tabla_2.campo.

condicion_seleccion

Una condición adicional: cuáles de las filas relacionadas modificar.

Opcional
MySQL 8.4
UPDATE Payments
SET unit_price = unit_price * 2
FROM Goods
WHERE Payments.good = Goods.good_id
    AND Goods.good_name LIKE '%caviar%';

En una subconsulta no se puede leer la misma tabla que está modificando UPDATE. Por ejemplo, así no podrás duplicar el precio de los pagos que están por debajo de la media:

MySQL 8.4
UPDATE Payments
SET unit_price = unit_price * 2
WHERE unit_price < (SELECT AVG(unit_price) FROM Payments);

La consulta terminará con un error:

MySQL 8.4
ERROR 1093 (HY000): You can't specify target table 'Payments' for update in FROM clause

Puedes sortear esta limitación envolviendo la subconsulta en otro SELECT. Así, primero se calcula el precio medio y se guarda en una tabla temporal, y la actualización lee ya de ella:

MySQL 8.4
UPDATE Payments
SET unit_price = unit_price * 2
WHERE unit_price < (
    SELECT avg_price
    FROM (SELECT AVG(unit_price) AS avg_price FROM Payments) AS stats
);

Errores típicos

Olvidar el WHERE

Una consulta sin condición modificará todas las filas de la tabla. Comprueba primero la condición con una consulta SELECT y solo después ponla en el UPDATE.

AND en lugar de coma en SET

La consulta de abajo no modifica dos columnas: todo lo que queda a la derecha del primer = se considera una única expresión lógica.

MySQL 8.4
UPDATE Payments
SET amount = 4 AND unit_price = 25
WHERE payment_id = 3;

La consulta se ejecutará sin errores y guardará en amount el resultado de esa expresión (0 o 1), mientras que unit_price no cambiará.

La consulta terminará con un error:

MySQL 8.4
ERROR: argument of AND must be type boolean, not type integer

Para modificar las dos columnas, las asignaciones se separan con una coma. Así SET sabe dónde termina una y empieza la siguiente:

MySQL 8.4
UPDATE Payments
SET amount = 4, unit_price = 25
WHERE payment_id = 3;

Comparar con NULL usando =

La condición WHERE campo = NULL no se cumple para ninguna fila, así que la consulta no modificará nada. Para comprobar si un valor está vacío, usa IS NULL.

Ponte a prueba

Algunos usuarios de la tabla Users no tienen indicada la fecha de confirmación del correo: la columna email_verified_at es NULL. ¿Cuántas filas modificará esta consulta?

MySQL 8.4
UPDATE Users
SET email_verified_at = '2024-01-01'
WHERE email_verified_at = NULL;