Daten aktualisieren, der UPDATE-Operator
Einmal eingetragene Daten bleiben nicht immer richtig: Menschen ändern ihren Nachnamen, in Zahlungen tauchen Tippfehler auf, Preise müssen neu berechnet werden. Um eine Zeile zu korrigieren, ohne sie zu löschen, verwendest du den Operator UPDATE.
Allgemeine Struktur einer Query mit UPDATE
UPDATE tabellen_name
SET tabellen_feld = wert [, ...]
[WHERE auswahl_bedingung];- [ ]optionaler Teil
- ...kann wiederholt werden
- tabellen_name
- Die Tabelle, deren Datensätze geändert werden.
- tabellen_feld
Die Spalte, die einen neuen Wert bekommt. Du kannst mehrere Paare tabellen_feld = wert durch Kommas getrennt angeben.
- wert
Der neue Wert: eine Zahl, ein String, ein Ausdruck wie price * 1.1 oder NULL.
- auswahl_bedingung
Welche Zeilen geändert werden. Ohne WHERE werden alle Zeilen der Tabelle geändert.
Optional
Andie (Andie Quincey) hat zum Beispiel seinen Nachnamen geändert und heißt jetzt Andie Anthony.
MySQL 8.4UPDATE FamilyMembers SET member_name = 'Andie Anthony' WHERE member_name = 'Andie Quincey';
| member_id | status | member_name | birthday |
|---|---|---|---|
| 1 | father | Headley Quincey | 1960-05-13T00:00:00.000Z |
| 2 | mother | Flavia Quincey | 1963-02-16T00:00:00.000Z |
| 3 | son | 1983-06-05T00:00:00.000Z | |
| 4 | daughter | Lela Quincey | 1985-06-07T00:00:00.000Z |
| 5 4 weitere Zeilen | daughter | Annie Quincey | 1988-04-10T00:00:00.000Z |
Mehrere Spalten ändern
Um mehrere Spalten auf einmal zu ändern, gib nach SET mehrere Paare tabellen_feld = wert durch Kommas getrennt an. Andie hat zum Beispiel 4 Packungen Milch zu je 25 gekauft, aber in der Zahlung mit der ID 3 wurden versehentlich 5 zu je 20 eingetragen. Korrigieren wir beide Spalten mit einer Query:
MySQL 8.4UPDATE Payments SET amount = 4, unit_price = 25 WHERE payment_id = 3;
| payment_id | date | family_member | good | amount | unit_price |
|---|---|---|---|---|---|
| 1 | 2005-02-12T00:00:00.000Z | 1 | 1 | 1 | 2000 |
| 2 | 2005-03-23T00:00:00.000Z | 2 | 1 | 1 | 2100 |
| 3 | 2005-05-14T00:00:00.000Z | 3 | 4 | ||
| 4 | 2005-07-22T00:00:00.000Z | 4 | 5 | 1 | 350 |
| 5 24 weitere Zeilen | 2005-07-26T00:00:00.000Z | 4 | 7 | 2 | 150 |
Alle aufgeführten Spalten ändern sich in denselben Zeilen — in denen, die die WHERE-Bedingung erfüllen.
Berechnete Werte
Einen neuen Wert kannst du aus dem alten berechnen, zum Beispiel alle Preise verdoppeln:
MySQL 8.4UPDATE Payments SET unit_price = unit_price * 2;
Im Ausdruck kannst du auch andere Spalten derselben Zeile verwenden, solange ihre Datentypen kompatibel sind. Erfassen wir zum Beispiel die Zahlung mit der ID 3 als eine einzige Position: In unit_price steht dann der Preis des gesamten Einkaufs und in amount eine Eins.
MySQL 8.4UPDATE Payments SET unit_price = unit_price * amount, amount = 1 WHERE payment_id = 3;
Bei einem UPDATE auf eine einzelne Tabelle werden die Zuweisungen in SET von links nach rechts ausgeführt, und der nächste Ausdruck sieht bereits den neuen Wert der Spalte. Vertauschst du die Zuweisungen, wird unit_price mit der gerade geschriebenen Eins multipliziert und bleibt unverändert:
MySQL 8.4UPDATE Payments SET amount = 1, unit_price = unit_price * amount WHERE payment_id = 3;
Ändere deshalb eine Spalte, von der andere Ausdrücke abhängen, immer als Letztes.
Alle Ausdrücke in SET werden mit den Werten berechnet, die die Zeile vor der Änderung hatte. Die Reihenfolge der Zuweisungen spielt deshalb keine Rolle. Diese Query liefert dasselbe Ergebnis:
MySQL 8.4UPDATE Payments SET amount = 1, unit_price = unit_price * amount WHERE payment_id = 3;
Aktualisieren anhand der Daten einer anderen Tabelle
Manchmal müssen die zu ändernden Zeilen anhand der Daten einer anderen Tabelle ausgewählt werden. Zum Beispiel hat sich herausgestellt, dass in allen Zahlungen für Kaviar nur der halbe Preis eingetragen wurde. Am einfachsten geht das mit einer Subquery in WHERE:
MySQL 8.4UPDATE Payments SET unit_price = unit_price * 2 WHERE good IN ( SELECT good_id FROM Goods WHERE good_name LIKE '%caviar%' );
Dasselbe erreichst du, indem du die Tabellen direkt in der UPDATE-Query mit JOIN verknüpfst:
UPDATE tabellen_name_1
JOIN tabellen_name_2 ON verbund_bedingung
SET tabellen_name_1.tabellen_feld = wert [, ...]
[WHERE auswahl_bedingung];- [ ]optionaler Teil
- ...kann wiederholt werden
- tabellen_name_1
- Die Tabelle, deren Datensätze geändert werden.
- tabellen_name_2
Die verknüpfte Tabelle, anhand deren Daten die Zeilen ausgewählt und die neuen Werte berechnet werden.
- verbund_bedingung
Wie die Zeilen verknüpft sind, z. B. tabellen_name_1.feld = tabellen_name_2.feld.
- auswahl_bedingung
Welche Zeilen geändert werden. Die Bedingung kann Spalten beider Tabellen prüfen.
Optional
MySQL 8.4UPDATE Payments JOIN Goods ON Payments.good = Goods.good_id SET Payments.unit_price = Payments.unit_price * 2 WHERE Goods.good_name LIKE '%caviar%';
Dasselbe erreichst du, indem du die zusätzlichen Tabellen nach FROM angibst:
UPDATE tabellen_name_1
SET tabellen_feld = wert [, ...]
FROM tabellen_name_2
WHERE verbund_bedingung
[AND auswahl_bedingung];- [ ]optionaler Teil
- ...kann wiederholt werden
- tabellen_name_1
Die Tabelle, deren Datensätze geändert werden. Nach FROM wird sie nicht wiederholt.
- tabellen_feld
Eine Spalte von tabellen_name_1. Sie wird ohne Tabellennamen angegeben.
- tabellen_name_2
Eine zusätzliche Tabelle, anhand deren Daten die Zeilen ausgewählt und die neuen Werte berechnet werden.
- verbund_bedingung
Wie die Zeilen verknüpft sind, z. B. tabellen_name_1.feld = tabellen_name_2.feld.
- auswahl_bedingung
Eine zusätzliche Bedingung: welche der verknüpften Zeilen geändert werden.
Optional
MySQL 8.4UPDATE Payments SET unit_price = unit_price * 2 FROM Goods WHERE Payments.good = Goods.good_id AND Goods.good_name LIKE '%caviar%';
Eine Subquery darf nicht dieselbe Tabelle lesen, die UPDATE ändert. Den Preis in Zahlungen unter dem Durchschnitt kannst du so zum Beispiel nicht verdoppeln:
MySQL 8.4UPDATE Payments SET unit_price = unit_price * 2 WHERE unit_price < (SELECT AVG(unit_price) FROM Payments);
Die Query bricht mit einem Fehler ab:
MySQL 8.4ERROR 1093 (HY000): You can't specify target table 'Payments' for update in FROM clause
Umgehen kannst du diese Einschränkung, indem du die Subquery in ein weiteres SELECT einbettest. Dann wird der Durchschnittspreis zuerst berechnet und in einer temporären Tabelle abgelegt, und das Update liest aus ihr:
MySQL 8.4UPDATE 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 );
Typische Fehler
Vergessenes WHERE
Eine Query ohne Bedingung ändert alle Zeilen der Tabelle. Prüfe die Bedingung zuerst mit einer SELECT-Query und setze sie erst dann in UPDATE ein.
AND statt Komma in SET
Die folgende Query ändert nicht zwei Spalten: Alles rechts vom ersten = gilt als ein einziger logischer Ausdruck.
MySQL 8.4UPDATE Payments SET amount = 4 AND unit_price = 25 WHERE payment_id = 3;
Die Query läuft ohne Fehler durch und schreibt das Ergebnis dieses Ausdrucks — 0 oder 1 — in amount, während unit_price unverändert bleibt.
Die Query bricht mit einem Fehler ab:
MySQL 8.4ERROR: argument of AND must be type boolean, not type integer
Um beide Spalten zu ändern, trennst du die Zuweisungen durch ein Komma. Daran erkennt SET, wo eine endet und die nächste beginnt:
MySQL 8.4UPDATE Payments SET amount = 4, unit_price = 25 WHERE payment_id = 3;
Vergleich mit NULL über =
Die Bedingung WHERE feld = NULL trifft auf keine Zeile zu, deshalb ändert die Query nichts. Um auf einen leeren Wert zu prüfen, verwende IS NULL.
Prüf dich selbst
Bei einigen Nutzern in der Tabelle Users fehlt das Datum der E-Mail-Bestätigung: Das Feld email_verified_at ist NULL. Wie viele Zeilen ändert diese Query?
MySQL 8.4UPDATE Users SET email_verified_at = '2024-01-01' WHERE email_verified_at = NULL;