PostgreSQL INSERT ON CONFLICT UPDATE (upsert) ใช้ค่าที่ยกเว้นทั้งหมด


151

เมื่อคุณเพิ่มแถว (PostgreSQL> = 9.5) และคุณต้องการให้ INSERT ที่เป็นไปได้ตรงกับการอัปเดตที่เป็นไปได้คุณสามารถเขียนได้ดังนี้:

INSERT INTO tablename (id, username, password, level, email) 
                VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') 
ON CONFLICT (id) DO UPDATE SET 
  id=EXCLUDED.id, username=EXCLUDED.username,
  password=EXCLUDED.password, level=EXCLUDED.level,email=EXCLUDED.email

มีวิธีที่สั้นกว่านี้ไหม? เพื่อบอกว่า: ใช้ค่า EXCLUDE ทั้งหมด

ใน SQLite ฉันเคยทำ:

INSERT OR REPLACE INTO tablename (id, user, password, level, email) 
                        VALUES (1, 'John', 'qwerty', 5, 'john@mail.com')

47
ไม่ใช่คำตอบที่แท้จริง แต่คุณสามารถใช้สัญกรณ์เล็กน้อยในไม่ช้า: INSERT INTO tablename (id, username, password, level, email) VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') ON CONFLICT (id) DO UPDATE SET (username, password, level, email) = (EXCLUDED.username, EXCLUDED.password, EXCLUDED.level, EXCLUDED.email).เกือบจะเหมือนกัน แต่ง่ายต่อการคัดลอก / วาง / จัดการรายการคอลัมน์
ออกลูก

อีกทางเลือกหนึ่งคือใช้คอลัมน์ jsonb และด้วยวิธีนี้คุณไม่ต้องกังวลเกี่ยวกับคอลัมน์
j จะ

คำตอบ:


172

Postgres ไม่ได้ใช้งานเทียบเท่ากับINSERT OR REPLACE. จากON CONFLICTเอกสาร (เน้นของฉัน):

อาจเป็นได้ทั้ง DO NOTHING หรือ DO UPDATE clause ที่ระบุรายละเอียดที่แน่นอนของการดำเนินการ UPDATE ที่จะดำเนินการในกรณีที่มีข้อขัดแย้ง

แม้ว่าจะไม่ได้ให้ชวเลขเพื่อทดแทน แต่ก็มีON CONFLICT DO UPDATEผลโดยทั่วไปมากกว่าเนื่องจากช่วยให้คุณตั้งค่าใหม่ตามข้อมูลที่มีอยู่ก่อน ตัวอย่างเช่น:

INSERT INTO users (id, level)
VALUES (1, 0)
ON CONFLICT (id) DO UPDATE
SET level = users.level + 1;

3
เพื่อเป็นการเตือนความจำคำว่า "on update" ไม่ได้มีความหมายเหมือนกับการ "ผสาน" ของมาตรฐาน SQL แม้ว่าโดยปกติแล้วจะสามารถใช้งานได้ในที่เดียวกัน ฉันมีกรณีที่คาดว่า "การอัปเดตความขัดแย้ง" จะเริ่มต้นขึ้น แต่ปัญหาที่แน่นอนในการแทรกไม่ได้ทำให้การอัปเดต (ซึ่งจะซ่อมแซมบันทึกที่เสียหาย) จะเริ่มทำงาน
pojo-guy

2
คุณสามารถขยาย "แต่ปัญหาที่แน่นอนในส่วนแทรกไม่ได้ทำให้เกิดการอัปเดต"
MrR

@ pojo-guy - ฉันไม่คิดว่าคุณจะเห็นคำถามจาก MrR - คุณสามารถขยาย "แต่ปัญหาที่แน่นอนในส่วนแทรกไม่ได้ทำให้เกิดการอัปเดต"
Randall

เมื่อคุณพยายามใช้การแทรก ... ในการอัปเดตใน postgresql ผลลัพธ์จะแตกต่างกันภายใต้สถานการณ์เฉพาะบางอย่างนอกเหนือจากการผสาน กรณีที่ฉันพบค่อนข้างคลุมเครือและเฉพาะเจาะจง แต่ก็ทำซ้ำได้ ไม่กี่เดือนแล้วฉันจึงไม่สามารถให้อะไรได้อีกในตอนนี้
pojo-guy

1
บางทีมันอาจไม่ใช่ข้อขัดแย้ง แต่มีข้อผิดพลาดอื่นเช่นข้อผิดพลาดประเภทฟิลด์?
MrR
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.