แทรกลงใน ... เลือกจาก ... ในการอัปเดตคีย์ซ้ำ


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อนุประโยคได้อย่างไร

คำตอบ:


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

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 clause
joHN

11
@john จะทำอย่างไรถ้าคำสั่ง SELECT มี GROUP BY clause
Kathir

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 เทียบกับตารางที่มีคีย์ที่ไม่ซ้ำกันหรือคีย์หลักมากกว่าหนึ่งรายการจะถูกทำเครื่องหมายว่าไม่ปลอดภัยด้วยเช่นกัน `
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 ทำ
แยร์

1
คุณยังสามารถใช้ field = VALUES (ฟิลด์) ในการอัปเดตที่ซ้ำกันได้ตามคำตอบในstackoverflow.com/questions/16935896/…
Erik Melkersson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.