INSERT IN… SELECT FROM… ON DUPLICATE KEY UPDATE

116

Ich mache eine Einfüge-Abfrage, bei der die meisten Spalten auf die neuen Werte aktualisiert werden müssten, wenn bereits ein eindeutiger Schlüssel vorhanden wäre. Es geht ungefähr so:

INSERT INTO lee(exp_id, created_by, 
                location, animal, 
                starttime, endtime, entct, 
                inact, inadur, inadist, 
                smlct, smldur, smldist, 
                larct, lardur, lardist, 
                emptyct, emptydur)
SELECT id, uid, t.location, t.animal, t.starttime, t.endtime, t.entct, 
       t.inact, t.inadur, t.inadist, 
       t.smlct, t.smldur, t.smldist, 
       t.larct, t.lardur, t.lardist, 
       t.emptyct, t.emptydur 
FROM tmp t WHERE uid=x
ON DUPLICATE KEY UPDATE ...; 
//update all fields to values from SELECT, 
//       except for exp_id, created_by, location, animal, 
//       starttime, endtime

Ich bin mir nicht sicher, wie die Syntax für die UPDATEKlausel lauten soll. Wie verweise ich auf die aktuelle Zeile aus der SELECTKlausel?

dnagirl
quelle

Antworten:

172

MySQL nimmt den Teil an, bevor das Gleiche auf die in der INSERT INTO-Klausel genannten Spalten verweist, und der zweite Teil verweist auf die SELECT-Spalten.

INSERT INTO lee(exp_id, created_by, location, animal, starttime, endtime, entct, 
                inact, inadur, inadist, 
                smlct, smldur, smldist, 
                larct, lardur, lardist, 
                emptyct, emptydur)
SELECT id, uid, t.location, t.animal, t.starttime, t.endtime, t.entct, 
       t.inact, t.inadur, t.inadist, 
       t.smlct, t.smldur, t.smldist, 
       t.larct, t.lardur, t.lardist, 
       t.emptyct, t.emptydur 
FROM tmp t WHERE uid=x
ON DUPLICATE KEY UPDATE entct=t.entct, inact=t.inact, ...
Marcus Adams
quelle
6
@dnagirl: TIPP: versuchen Sie nicht , eine der PK Spalten zu aktualisieren, nur diejenigen , die Notwendigkeit , die Aktualisierung gehen in die Liste
Lexu
45
Ihre vorgeschlagene Syntax funktioniert und die t.ist erforderlich. Ich habe auch einen Artikel über xaprb ( xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysql ) gefunden, der diese Syntax verwendet : on duplicate key update b = values(b), c = values(c). Das funktioniert auch.
Dnagirl
9
Hinweis: Dies funktioniert nicht, wenn die SELECT-Anweisung eine GROUP BY-Klausel enthält
joHN
11
@ John Was tun, wenn die SELECT-Anweisung eine GROUP BY-Klausel enthält
Kathir
2
dev.mysql.com/doc/refman/5.6/de/insert-on-duplicate.html sagt `in MySQL 5.6.4 und höher, INSERT ... SELECT ON DUPLICATE KEY UPDATE-Anweisungen werden für die anweisungsbasierte Replikation als unsicher gekennzeichnet ... Ab MySQL 5.6.6 wird außerdem eine INSERT ... ON DUPLICATE KEY UPDATE-Anweisung für eine Tabelle mit mehr als einem eindeutigen oder Primärschlüssel als unsicher markiert. "
Abdul Muneer
51

Ich bin zwar sehr spät dran, aber nachdem ich einige berechtigte Fragen für diejenigen gesehen habe, die die INSERT-SELECTAbfrage mit GROUP BYKlausel verwenden wollten , habe ich mir die Lösung dafür ausgedacht.

Wenn ich die Antwort von Marcus Adams weiter nehme und darin abrechne GROUP BY, würde ich das Problem auf diese Weise lösenSubqueries in the FROM Clause

INSERT INTO lee(exp_id, created_by, location, animal, starttime, endtime, entct, 
                inact, inadur, inadist, 
                smlct, smldur, smldist, 
                larct, lardur, lardist, 
                emptyct, emptydur)
SELECT sb.id, uid, sb.location, sb.animal, sb.starttime, sb.endtime, sb.entct, 
       sb.inact, sb.inadur, sb.inadist, 
       sb.smlct, sb.smldur, sb.smldist, 
       sb.larct, sb.lardur, sb.lardist, 
       sb.emptyct, sb.emptydur
FROM
(SELECT id, uid, location, animal, starttime, endtime, entct, 
       inact, inadur, inadist, 
       smlct, smldur, smldist, 
       larct, lardur, lardist, 
       emptyct, emptydur 
FROM tmp WHERE uid=x
GROUP BY location) as sb
ON DUPLICATE KEY UPDATE entct=sb.entct, inact=sb.inact, ...
iCurious
quelle
8
Dies ist die richtige Antwort für Fragen mit COUNT, GROUP usw. Danke.
Kostanos
Vielen Dank, Alter! Dieser Ansatz hat mir sehr gut gefallen, insbesondere, weil ich damit einen Mechanismus wie Continuous Query erstellen kann, wie es InfluxDB tut.
Miere
1
Sie können auch field = VALUES (field) in der doppelten Aktualisierung verwenden, wie in der Antwort in stackoverflow.com/questions/16935896/…
Erik Melkersson