INSÉRER DANS… CHOISIR À PARTIR DE… À LA MISE À JOUR DE LA CLÉ EN DOUBLE

116

Je fais une requête d'insertion où la plupart des nombreuses colonnes devraient être mises à jour avec les nouvelles valeurs si une clé unique existait déjà. Ca fait plutot comme ca:

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

Je ne sais pas quelle UPDATEdevrait être la syntaxe de la clause. Comment faire référence à la ligne actuelle de la SELECTclause?

dnagirl
la source

Réponses:

172

MySQL assumera la partie avant l'égale référence les colonnes nommées dans la clause INSERT INTO, et la deuxième partie référence les colonnes SELECT.

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
la source
6
@dnagirl: ASTUCE: n'essayez de mettre à jour aucune des colonnes PK, seules celles qui nécessitent une mise à jour vont dans la liste
lexu
45
Votre syntaxe suggérée fonctionne et t.est obligatoire. J'ai aussi trouvé un article sur xaprb ( xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysql ) qui utilise cette syntaxe: on duplicate key update b = values(b), c = values(c). Cela fonctionne également.
dnagirl
9
Remarque: cela ne fonctionnera pas lorsque l'instruction SELECT a une clause GROUP BY
joHN
11
@john Que faire si l'instruction SELECT a une clause GROUP BY
Kathir
2
dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html dit `dans MySQL 5.6.4 et versions ultérieures, INSERT ... SELECT ON DUPLICATE KEY UPDATE les instructions sont marquées comme non sécurisées pour la réplication basée sur des instructions ... De plus, à partir de MySQL 5.6.6, une instruction INSERT ... ON DUPLICATE KEY UPDATE contre une table ayant plus d'une clé unique ou primaire est également marquée comme non sécurisée. ''
Abdul Muneer
51

Bien que je sois très en retard, mais après avoir vu des questions légitimes pour ceux qui voulaient utiliser une INSERT-SELECTrequête avec GROUP BYclause, j'ai trouvé le travail autour de cela.

En poussant plus loin la réponse de Marcus Adams et en y rendant GROUP BYcompte, voici comment je résoudrais le problème en utilisantSubqueries 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
la source
8
C'est la bonne réponse pour les requêtes avec COUNT, GROUP etc. Merci.
Kostanos
Merci beaucoup, mec! J'ai beaucoup aimé cette approche, spécialement parce qu'elle me permet de créer un mécanisme comme la requête continue, ce que fait InfluxDB.
Miere
1
Vous pouvez également utiliser field = VALUES (field) dans la mise à jour en double comme dans la réponse dans stackoverflow.com/questions/16935896/...
Erik Melkersson