插入……选择……重复键更新


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子句引用当前行?

Answers:


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列,只有那些需要更新的列会进入列表
lexu 2010年

45
您建议的语法有效,并且t.是必需的。我还在xaprb上找到了一篇使用以下语法的文章(xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysqlon duplicate key update b = values(b), c = values(c)。这也有效。
dnagirl

9
注意:当SELECT语句具有GROUP BY子句时,这将不起作用
joHN 2014年

11
@john如果SELECT语句具有GROUP BY子句怎么办
Kathir

2
dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html在MySQL 5.6.4及更高版本中表示INSERT ... SELECT ... DUPLICATE KEY UPDATE语句被标记为对基于语句的复制不安全...此外,从MySQL 5.6.6开始,针对具有多个唯一或主键的表的INSERT ... ON DUPLICATE KEY UPDATE语句也被标记为不安全。`–
Abdul Muneer

51

尽管我对此很迟,但是在为那些想使用带INSERT-SELECT查询GROUP BY子句的人看到一些合理的问题之后,我想出了解决方法。

进一步了解Marcus Adams的答案并进行核算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, ...

8
这是使用COUNT,GROUP等进行查询的正确答案。谢谢。
Kostanos

非常感谢你,老兄!我真的很喜欢这种方法,特别是因为它允许我创建一种像Continuous Query这样的机制,InfluxDB就是这样做的。
Miere

1
您也可以在重复更新中使用field = VALUES(field),如在stackoverflow.com/questions/16935896/…
Erik Melkersson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.