อัปเดต (2015-08-20):
ขณะนี้มีการดำเนินการอย่างเป็นทางการสำหรับการจัดการ upserts ผ่านการใช้งานON CONFLICT DO UPDATE
(เอกสารอย่างเป็นทางการ) ในขณะที่เขียนนี้คุณลักษณะนี้อาศัยอยู่ในปัจจุบัน PostgreSQL 9.5 อัลฟ่า 2 ซึ่งสามารถดาวน์โหลดได้ที่นี่: ไดเรกทอรีแหล่ง Postgres
นี่คือตัวอย่างสมมติว่าitem_id
เป็นคีย์หลักของคุณ:
INSERT INTO my_table
(item_id, price)
VALUES
(123456, 10.99)
ON
CONFLICT (item_id)
DO UPDATE SET
price = EXCLUDED.price
โพสต์ต้นฉบับ ...
นี่คือการติดตั้งที่ฉันใช้เมื่อต้องการจะมองเห็นว่ามีการแทรกหรือการอัพเดตเกิดขึ้นหรือไม่
คำจำกัดความของupsert_data
คือการรวมค่าลงในทรัพยากรเดียวแทนที่จะต้องระบุราคาและ item_id สองครั้ง: หนึ่งครั้งสำหรับการอัปเดตอีกครั้งสำหรับการแทรก
WITH upsert_data AS (
SELECT
'19.99'::numeric(10,2) AS price,
'abcdefg'::character varying AS item_id
),
update_outcome AS (
UPDATE pricing_tbl
SET price = upsert_data.price
FROM upsert_data
WHERE pricing_tbl.item_id = upsert_data.item_id
RETURNING 'update'::text AS action, item_id
),
insert_outcome AS (
INSERT INTO
pricing_tbl
(price, item_id)
SELECT
upsert_data.price AS price,
upsert_data.item_id AS item_id
FROM upsert_data
WHERE NOT EXISTS (SELECT item_id FROM update_outcome LIMIT 1)
RETURNING 'insert'::text AS action, item_id
)
SELECT * FROM update_outcome UNION ALL SELECT * FROM insert_outcome
หากคุณไม่ชอบการใช้งานupsert_data
นี่คือการใช้งานแบบอื่น:
WITH update_outcome AS (
UPDATE pricing_tbl
SET price = '19.99'
WHERE pricing_tbl.item_id = 'abcdefg'
RETURNING 'update'::text AS action, item_id
),
insert_outcome AS (
INSERT INTO
pricing_tbl
(price, item_id)
SELECT
'19.99' AS price,
'abcdefg' AS item_id
WHERE NOT EXISTS (SELECT item_id FROM update_outcome LIMIT 1)
RETURNING 'insert'::text AS action, item_id
)
SELECT * FROM update_outcome UNION ALL SELECT * FROM insert_outcome