MySql Table Insert หากไม่มีการอัพเดตเป็นอย่างอื่น


106
UPDATE AggregatedData SET datenum="734152.979166667", 
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";

ใช้งานได้ถ้าdatenumมีอยู่ แต่ฉันต้องการแทรกข้อมูลนี้เป็นแถวใหม่หากdatenumไม่มีอยู่

อัปเดต

ฐานข้อมูลไม่ซ้ำกัน แต่ไม่ใช่คีย์หลัก


2
"ฐานข้อมูล" ไม่ซ้ำกันหรือไม่? คุณสามารถใช้INSERT ... ในการอัปเดตคีย์ซ้ำได้หากเป็น
เจ

คำตอบ:


143

ไยถูกต้องว่าควรใช้INSERT ... ON DUPLICATE KEY UPDATE.

โปรดทราบว่าคุณไม่จำเป็นต้องรวมข้อมูลไว้ในส่วนคำสั่งอัปเดตเนื่องจากเป็นรหัสเฉพาะดังนั้นจึงไม่ควรเปลี่ยนแปลง คุณจำเป็นต้องรวมคอลัมน์อื่น ๆ ทั้งหมดจากตารางของคุณ คุณสามารถใช้VALUES()ฟังก์ชันเพื่อให้แน่ใจว่ามีการใช้ค่าที่เหมาะสมเมื่ออัปเดตคอลัมน์อื่น ๆ

นี่คือการอัปเดตของคุณเขียนใหม่โดยใช้INSERT ... ON DUPLICATE KEY UPDATEไวยากรณ์ที่เหมาะสมสำหรับ MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)

18
โปรดใช้ความระมัดระวังในการใช้ INSERT ... ON DUPLICATE KEY UPDATE บนตารางเทียบกับตารางที่มีคีย์เฉพาะหรือคีย์หลักมากกว่าหนึ่งคีย์ นำมาจากเอกสาร MySQL : นอกจากนี้เริ่มต้นด้วย MySQL 5.5.24 คำสั่ง INSERT ... ON DUPLICATE KEY UPDATE เทียบกับตารางที่มีคีย์ที่ไม่ซ้ำกันหรือคีย์หลักมากกว่าหนึ่งรายการยังถูกทำเครื่องหมายว่าไม่ปลอดภัย (ข้อบกพร่อง # 11765650 ข้อบกพร่อง # 58637)คำอธิบายข้อผิดพลาด 58637 bugs.mysql.com/bug.php?id=58637
บรอดแบนด์

1
อาจจำเป็นต้องสร้าง UNIQUEข้อ จำกัดTimestampโดยใช้ALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt

@broadband คุณสามารถใช้คีย์คอมโพสิตเพื่อหลีกเลี่ยงข้อผิดพลาดนี้
Kareem

16

ลองใช้สิ่งนี้ :

หากคุณระบุON DUPLICATE KEY UPDATEและมีการแทรกแถวที่จะทำให้เกิดค่าที่ซ้ำกันในUNIQUE index orPRIMARY KEY , MySQL performs an [UPDATE`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) ของแถวเก่า ..

ON DUPLICATE KEY UPDATEข้อสามารถมีได้รับมอบหมายคอลัมน์หลายคั่นด้วยเครื่องหมายจุลภาค

ด้วยON DUPLICATE KEY UPDATEค่าแถวที่ได้รับผลกระทบต่อแถวคือ 1 ถ้าแถวนั้นถูกแทรกเป็นแถวใหม่ 2 ถ้าแถวที่มีอยู่ได้รับการอัพเดตและ 0 ถ้าแถวที่มีอยู่ถูกตั้งค่าเป็นค่าปัจจุบัน หากคุณระบุCLIENT_FOUND_ROWSแฟล็กmysql_real_connect()เมื่อเชื่อมต่อกับmysqldค่าแถวที่ได้รับผลกระทบคือ 1 (ไม่ใช่ 0) หากแถวที่มีอยู่ถูกตั้งค่าเป็นค่าปัจจุบัน ...


แต่ข้อมูลของฉันไม่ใช่คีย์หลัก
OHLÁLÁ

ดังนั้นในกรณีของฉันวิธีแก้ปัญหาคืออะไรฉันลองวิธีนี้โดยไม่มีวิธีแก้ปัญหาใด ๆ : INSERT INTO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) VALUES ('1', '2', '3') บนข้อมูลอัปเดตคีย์ซ้ำ ฐานข้อมูล;
OHLÁLÁ

1
ข้อมูลควรจะไม่ซ้ำกันหรือไม่? ถ้าใช่ให้เพิ่มดัชนีเฉพาะเข้าไป (หากยังไม่ได้เพิ่ม) จากนั้นจะใช้งานได้ อ้างอิงdev.mysql.com/doc/refman/5.1/en/alter-table.htmlสำหรับวิธีโฆษณาดัชนี UNIQUE
ใจ

ตอนนี้ฉันกำหนด datenum ว่าไม่ซ้ำกันและมันก็ใช้ได้ดีขอบคุณ
OHLÁLÁ

1
แค่ลิงค์อาจจะให้คำตอบ
Andrew

0

ฉันมีสถานการณ์ที่ฉันจำเป็นต้องอัปเดตหรือแทรกบนตารางตามสองฟิลด์ (คีย์ต่างประเทศทั้งสอง) ซึ่งฉันไม่สามารถตั้งค่าข้อ จำกัด ที่ไม่ซ้ำกันได้ (ดังนั้น INSERT ... ในการอัปเดตคีย์ซ้ำจะไม่ทำงาน) นี่คือสิ่งที่ฉันใช้:

replace into last_recogs (id, hasher_id, hash_id, last_recog) 
  select l.* from 
    (select id, hasher_id, hash_id, [new_value] from last_recogs 
     where hasher_id in (select id from hashers where name=[hasher_name])
     and hash_id in (select id from hashes where name=[hash_name]) 
     union 
     select 0, m.id, h.id, [new_value] 
     from hashers m cross join hashes h 
     where m.name=[hasher_name] 
     and h.name=[hash_name]) l 
  limit 1;

ตัวอย่างนี้ถูกคัดลอกมาจากฐานข้อมูลหนึ่งของฉันโดยพารามิเตอร์อินพุต (สองชื่อและตัวเลข) แทนที่ด้วย [hasher_name], [hash_name] และ [new_value] SELECT ที่ซ้อนกัน ... LIMIT 1 จะดึงระเบียนแรกที่มีอยู่หรือระเบียนใหม่ (last_recogs.id เป็นคีย์หลักที่สร้างขึ้นโดยอัตโนมัติ) และใช้เป็นค่าที่ป้อนลงใน REPLACE INTO


REPLACE แทรกแถวใหม่เสมอ! มันแค่ลบต้นฉบับที่มีอยู่แล้ว!
jasie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.