WSTAW DO… WYBIERZ Z… NA DUPLIKOWANEJ AKTUALIZACJI KLUCZA

116

Wykonuję zapytanie wstawiające, w którym większość z wielu kolumn musiałaby zostać zaktualizowana do nowych wartości, jeśli unikatowy klucz już istniał. To wygląda mniej więcej tak:

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

Nie jestem pewien, jaka UPDATEpowinna być składnia klauzuli. Jak mam odwołać się do bieżącego wiersza z SELECTklauzuli?

dnagirl
źródło

Odpowiedzi:

172

MySQL przyjmie część, zanim równa się odniesie do kolumn wymienionych w klauzuli INSERT INTO, a druga część odwoła się do kolumn 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
źródło
6
@dnagirl: WSKAZÓWKA: nie próbuj aktualizować żadnej z kolumn PK, tylko te, które wymagają aktualizacji, trafiają na listę
lexu
45
Twoja sugerowana składnia działa i t.jest wymagana. Znalazłem również artykuł o xaprb ( xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysql ), który używa tej składni: on duplicate key update b = values(b), c = values(c). To też działa.
dnagirl
9
Uwaga: to nie zadziała, gdy instrukcja SELECT zawiera klauzulę GROUP BY
joHN
11
@john Co zrobić, jeśli instrukcja SELECT zawiera klauzulę GROUP BY
Kathir
2
dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html mówi: `w MySQL 5.6.4 i nowszych INSERT ... SELECT ON DUPLICATE KEY UPDATE instrukcje są oznaczane jako niebezpieczne dla replikacji opartej na instrukcjach ... Ponadto, począwszy od MySQL 5.6.6, instrukcja INSERT ... ON DUPLICATE KEY UPDATE w odniesieniu do tabeli mającej więcej niż jeden klucz unikalny lub podstawowy jest również oznaczana jako niebezpieczna. ”
Abdul Muneer
51

Chociaż jestem na to bardzo spóźniony, ale po zobaczeniu kilku uzasadnionych pytań dla tych, którzy chcieli użyć INSERT-SELECTzapytania z GROUP BYklauzulą, wymyśliłem obejście tego problemu .

Biorąc dalej odpowiedź Marcusa Adamsa i rozliczając się GROUP BYw niej, w ten sposób rozwiązałbym problem za pomocąSubqueries 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
źródło
8
To jest właściwa odpowiedź w przypadku zapytań zawierających COUNT, GROUP itd. Dzięki.
Kostanos
Dziękuję bardzo, stary! Bardzo podobało mi się to podejście, szczególnie dlatego, że pozwala mi stworzyć mechanizm taki jak Continuous Query, coś, co robi InfluxDB.
Miere
1
Możesz również użyć pola = WARTOŚCI (pole) w zduplikowanej aktualizacji, jak w odpowiedzi na stackoverflow.com/questions/16935896/ ...
Erik Melkersson