INSERT INTO… SELECT FROM… ON DUPLICATE KEY UPDATE

116

Я выполняю запрос на вставку, в котором необходимо обновить большинство столбцов до новых значений, если уникальный ключ уже существует. Это выглядит примерно так:

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

Я не уверен, каким UPDATEдолжен быть синтаксис этого предложения. Как мне сослаться на текущую строку из SELECTпредложения?

dnagirl
источник

Ответы:

172

MySQL предполагает, что часть до равенства ссылается на столбцы, указанные в предложении INSERT INTO, а вторая часть ссылается на столбцы 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, ...
Маркус Адамс
источник
6
@dnagirl: СОВЕТ: не пытайтесь обновить какие-либо столбцы PK, в список
войдут
45
Предлагаемый вами синтаксис работает, и t.требуется. Я также нашел статью о xaprb ( xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysql ) , который использует этот синтаксис: on duplicate key update b = values(b), c = values(c). Это тоже работает.
dnagirl
9
Примечание: это не сработает, если в инструкции SELECT есть предложение GROUP BY
joHN
11
@john Что делать, если в инструкции SELECT есть предложение GROUP BY
Катир
2
dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html говорит, что `в MySQL 5.6.4 и более поздних версиях INSERT ... SELECT ON DUPLICATE KEY UPDATE помечены как небезопасные для репликации на основе операторов ... Кроме того, начиная с MySQL 5.6.6, оператор INSERT ... ON DUPLICATE KEY UPDATE для таблицы, имеющей более одного уникального или первичного ключа, также помечается как небезопасный. '
Абдул Мунер
51

Хотя я очень опоздал с этим, но после того, как увидел несколько законных вопросов для тех, кто хотел использовать INSERT-SELECTзапрос с GROUP BYпредложением, я придумал для этого работу.

Продолжая ответ Маркуса Адамса и бухгалтерский учет GROUP BYв нем, я бы решил проблему, используя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
источник
8
Это правильный ответ для запросов с COUNT, GROUP и т. Д. Спасибо.
Костанос,
Спасибо тебе большое, чувак! Мне очень понравился этот подход, особенно потому, что он позволяет мне создавать такой механизм, как Continuous Query, что делает InfluxDB.
Miere
1
Вы также можете использовать field = VALUES (field) в дублированном обновлении, как в ответе на stackoverflow.com/questions/16935896/…
Эрик Мелкерссон