In eine MySQL-Tabelle einfügen oder aktualisieren, falls vorhanden

875

Ich möchte einer Datenbanktabelle eine Zeile hinzufügen, aber wenn eine Zeile mit demselben eindeutigen Schlüssel vorhanden ist, möchte ich die Zeile aktualisieren.

Zum Beispiel:

insert into table (id, name, age) values(1, "A", 19)

Angenommen, der eindeutige Schlüssel lautet id, und in meiner Datenbank gibt es eine Zeile mit id = 1. In diesem Fall möchte ich diese Zeile mit diesen Werten aktualisieren. Normalerweise gibt dies einen Fehler.
Wenn ich es benutze insert IGNORE, wird der Fehler ignoriert, aber es wird immer noch nicht aktualisiert.

Keshan
quelle
5
SQL benötigt für diesen Anwendungsfall eine offizielle Syntax, die das Duplizieren von Werten in der Syntax nicht erzwingt und den Primärschlüssel beibehält.
Pete Alvin
Informationen
Kris Roofe
Vorsichtsmaßnahme: Ab Version 5.7 unterstützt dieser Ansatz die WHERE-Klausel als Teil der INSERT / UPDATE-Operation nicht direkt. Außerdem zählt ein UPDATE tatsächlich als zwei separate Vorgänge (DELETE und INSERT) ... für den Fall, dass dies für Prüfungszwecke von Bedeutung ist. (Learnbit)
Dreftymac

Antworten:

1599

Verwenden INSERT ... ON DUPLICATE KEY UPDATE

ABFRAGE:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name="A", age=19
Donnie
quelle
86
+1 Soweit ich festgestellt habe, ist diese Methode für Auto-Inkrement-Schlüssel und andere eindeutige Schlüsselkollisionen weniger problematisch als REPLACE INTO und effizienter.
Andrew Ensley
46
Ich weiß, dass Sie alle darauf anspielen, aber ich möchte für andere explizit sein. Wenn die von Ihnen eingegebene ID NICHT der PRIMARY KEY oder UNIQUE ist, funktioniert dies nicht. Dies funktionierte anfangs nicht für mich, da meine ID nicht eindeutig war.
Keven
7
Ich frage mich , warum affected row countErgebnisse in 2wann (auf doppelten Schlüssel) einreihig erfolgreich zu aktualisieren? Hat sonst noch jemand dieses Ergebnis gehabt? (Die Daten werden korrekt aktualisiert: was bedeutet, dass nur 1 Zeile aktualisiert wird)
Dimitry K
15
Dies ist etwas spät, aber trotzdem: Im Handbuch wird angegeben, dass Aktualisierungen ON DUPLICATE KEY UPDATEdie betroffenen Zeilen um 2 erhöhen. Es wird 0 gemeldet, wenn tatsächlich nichts aktualisiert wird (wie beim regulären UPDATE).
Vatev
61
Beachten Sie auch, dass Sie VALUES (Name) verwenden können, um auf den Wert zu verweisen, den Sie einfügen möchten, z. B. INSERT INTO-Tabelle (ID, Name, Alter). VALUES (1, "A", 19) ON DUPLICATE KEY UPDATE name = VALUES (Name) , Alter = WERTE (Alter)
Neugieriger Sam
246

Schauen Sie sich REPLACE an

http://dev.mysql.com/doc/refman/5.0/en/replace.html

REPLACE into table (id, name, age) values(1, "A", 19)
Martin Schapendonk
quelle
11
@Piontek Weil dieser kürzer und leichter zu verstehen ist und niemand erklärt hat, warum "Einfügen auf Duplikat" besser ist.
Mr_Chimp
77
Es ändert die IDs des Datensatzes und kann somit ausländische Referenzen zerstören.
Boh
102
Das andere Problem bei REPLACE INTO besteht darin, dass Sie Werte für ALLE Felder angeben müssen. Andernfalls gehen Felder verloren oder werden durch Standardwerte ersetzt. REPLACE INTO löscht im Wesentlichen die Zeile, falls vorhanden, und fügt die neue Zeile ein. Wenn Sie im Beispiel 'REPLACE INTO-Tabellenwerte (ID, Alter) (1, 19) verwendet haben, wird das Namensfeld null.
Dale
33
Dies ist tatsächlich das Löschen der gesamten Zeile und das Ausführen eines neuen EINFÜGENS.
MJB
8
@mjb Daher benötigen Sie DELETE-Berechtigungen, die Sie am besten nicht haben sollten, wenn Sie sie nicht benötigen. Der Datenbankbenutzer meiner Umgebung verfügt nur über INSERT- und UPDATE-Berechtigungen, sodass REPLACE nicht funktioniert.
ndm13
54

Verwenden Sie bei Verwendung der Stapeleinfügung die folgende Syntax:

INSERT INTO TABLE (id, name, age) VALUES (1, "A", 19), (2, "B", 17), (3, "C", 22)
ON DUPLICATE KEY UPDATE
    name = VALUES (name),
    ...
Fabiano Souza
quelle
Sehr nützlich, wenn Sie den neuen Wert manipulieren möchten
Hunger
Wenn VALUES(name)dies nicht funktioniert, können Sie versuchenname = 'name_value',...;
Son Pham
26

Probieren Sie es aus:

INSERT INTO table (id, name, age) VALUES (1, 'A', 19) ON DUPLICATE KEY UPDATE id = id + 1;

Hoffe das hilft.

Luis Reyes
quelle
6
Eigentlich muss ich die neuen Werte nicht zu einer anderen Zeile mit einer neuen ID hinzufügen, sondern ich möchte die vorhandenen Werte von id = 1 durch diese Werte ersetzen. (Wie ich verstehe, erhöht dies die ID und fügt die Daten hinzu)
Keshan
49
Ich glaube nicht, dass er die ID bei Duplikaten um eins erhöhen möchte.
Donnie
7
"Übertretung" ist nicht das Wort, das Sie suchen :) Leider habe ich jetzt "Übertretung" gesehen, ich kann das tatsächliche Wort nicht mehr visualisieren ..
mwfearnley
1
Haben Sie nach "Traversen" oder "Deckblättern" gesucht?
Chris Dev
4
@mwfearnley Das Wort, das Sie zu visualisieren versuchten, ist "transzendiert". Hat nur anderthalb Jahre gedauert :-)
Michael Krebs
20

Versuche dies:

INSERT INTO table (id,name,age) VALUES('1','Mohammad','21') ON DUPLICATE KEY UPDATE name='Mohammad',age='21'

Hinweis:
Wenn hier id der Primärschlüssel ist, werden nach dem ersten Einfügen bei id='1'jedem id='1'Einfügeversuch Name und Alter aktualisiert, und das Alter des vorherigen Namens ändert sich.

Rasel
quelle
Ich möchte ohne ID arbeiten . Haben Sie es ohne Primärschlüssel versucht?
ersks
@ersks sehen die Frage. Benutzer fragte, wann es einen eindeutigen Schlüssel gibt
Rasel
Ich habe das verstanden, aber ich versuche mein Problem zu lösen, bei dem diese einzigen Werte bekannt sind. In einer solchen Situation schrieb ich den obigen Kommentar in der Hoffnung auf die richtige Lösung.
ersks
15
INSERT IGNORE INTO table (id, name, age) VALUES (1, "A", 19);

INSERT INTO TABLE (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE NAME = "A", AGE = 19;

REPLACE INTO table (id, name, age) VALUES(1, "A", 19);

Alle diese Lösungen funktionieren in Bezug auf Ihre Frage.

Wenn Sie Einzelheiten zu dieser Erklärung erfahren möchten, besuchen Sie diesen Link

Dilraj Singh
quelle
REPLACEist im verknüpften Dokument nicht dokumentiert.
Ray Baxter
SQL-Abfragen voller Tippfehler, Ihre Beispiele funktionieren nicht. Es ist INSERT IN TABLE (nicht IN TABLE) und ON DUPLICATE KEY UPDATE (nicht ON DUPLICATE UPDATE SET). Ich bin mir nicht sicher, wer das befürwortet
Robert Sinclair
1
Entschuldigung für den Tippfehler. Vielen Dank für die Korrektur
Dilraj Singh
11

Bei Verwendung von SQLite:

REPLACE into table (id, name, age) values(1, "A", 19)

Vorausgesetzt, das idist der Primärschlüssel. Oder es wird einfach eine weitere Zeile eingefügt. Siehe INSERT (SQLite).

DawnSong
quelle
Was replace intogenau ist, ist "Einfügen in oder Aktualisieren, wenn vorhanden". @Owl
DawnSong
+1 (1 von 3) Ich fand, dass dies für meine Situation funktioniert - ich musste eine vorhandene Zeile durch einen eindeutigen Schlüssel ersetzen oder, falls nicht vorhanden, die Zeile hinzufügen. Einfachste Lösung hier.
Therobyouknow
(2 von 3) Meine Anfrage:CREATE TRIGGER worklog_update AFTER INSERT ON worklog FOR EACH ROW REPLACE INTO support_time_monthly_hours ( ProjectID, monthTotalTime, Year, Month ) SELECT jiraissue.PROJECT, SUM(worklog.timeworked), YEAR(CURRENT_DATE()), MONTH(CURRENT_DATE()) FROM worklog, jiraissue WHERE worklog.issueid = jiraissue.ID AND jiraissue.PROJECT = (SELECT PROJECT FROM jiraissue WHERE NEW.issueid = jiraissue.ID ) AND worklog.startdate BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01 00:00:00') AND NOW();
Therobyouknow
(3 von 3) Verwandte Frage / Antwort stackoverflow.com/questions/41767517/…
therobyouknow
2
Das Problem bei MySQL ist, dass durch Ersetzen andere Werte entfernt werden, falls sie nicht bereitgestellt werden. Allerdings ist @ fabiano-souza Lösung besser geeignet
Quamber Ali
11

Nur weil ich hier nach dieser Lösung gesucht habe, aber um von einer anderen identisch strukturierten Tabelle zu aktualisieren (in meinem Fall Website-DB auf Live-DB testen):

INSERT  live-db.table1
SELECT  *
FROM    test-db.table1 t
ON DUPLICATE KEY UPDATE
        ColToUpdate1 = t.ColToUpdate1,
        ColToUpdate2 = t.ColToUpdate2,
        ...

Wie an anderer Stelle erwähnt, müssen nur die Spalten eingefügt werden, die Sie aktualisieren möchten ON DUPLICATE KEY UPDATE.

Keine Notwendigkeit, die Spalten im INSERToder SELECTaufzulisten, obwohl ich damit einverstanden bin, ist es wahrscheinlich eine bessere Praxis.

SteveCinq
quelle
4

Falls Sie ein non-primaryFeld als Kriterium / Bedingung für erstellen möchten ON DUPLICATE, können Sie einen UNIQUE INDEXSchlüssel für diese Tabelle erstellen, um das auszulösen DUPLICATE.

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`);

Wenn Sie zwei Felder kombinieren möchten, um sie in der Tabelle eindeutig zu machen, können Sie dies erreichen, indem Sie dem letzten Parameter mehr hinzufügen.

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`, `age`);

Beachten Sie, dass Sie zuerst alle Daten löschen müssen, deren Wert nameund ageWert in den anderen Zeilen gleich ist.

DELETE table FROM table AS a, table AS b WHERE a.id < b.id 
AND a.name <=> b.name AND a.age <=> b.age;

Danach sollte es das ON DUPLICATEEreignis auslösen .

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name = VALUES(name), age = VALUES(age)
Reich
quelle
2

In meinem Fall habe ich unten Abfragen erstellt, aber in der ersten Abfrage, wenn id1 bereits vorhanden ist und das Alter bereits vorhanden ist, danach, wenn Sie die erste Abfrage ohne erstellen, ist ageder Wert von agekeine

REPLACE into table SET `id` = 1, `name` = 'A', `age` = 19

Um das oben genannte Problem zu vermeiden, erstellen Sie eine Abfrage wie unten

INSERT INTO table SET `id` = '1', `name` = 'A', `age` = 19 ON DUPLICATE KEY UPDATE `id` = "1", `name` = "A",`age` = 19

möge es dir helfen ...

Renish Gotecha
quelle
2
Weiß jemand, warum wir die Werte zweimal zuweisen müssen? Warum können wir mit MySQL die Abfrage nicht bei ON DUPLICATE KEY UPDATE beenden, ohne alle Zuweisungsanweisungen zu duplizieren? Einige Datenbanktabellen haben viele Spalten, und dies scheint redundant / unbegründet zu sein. Ich verstehe, warum wir die Option für alternative Aufgaben haben, aber warum nicht auch die Option, sie wegzulassen? Nur neugierig, wenn jemand weiß.
Blaues Wasser
2

Falls Sie das alte Feld behalten möchten (z. B. Name). Die Abfrage lautet:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name=name, age=19;
Xman Klassik
quelle