UPDATE (2015-08-20):
Sekarang ada implementasi resmi untuk menangani upert melalui penggunaan ON CONFLICT DO UPDATE
(dokumentasi resmi). Pada saat penulisan ini, fitur ini saat ini berada di PostgreSQL 9.5 Alpha 2, yang tersedia untuk diunduh di sini: Direktori sumber postgres .
Berikut ini sebuah contoh, dengan asumsi item_id
adalah Kunci Utama Anda:
INSERT INTO my_table
(item_id, price)
VALUES
(123456, 10.99)
ON
CONFLICT (item_id)
DO UPDATE SET
price = EXCLUDED.price
Pos Asli ...
Ini adalah implementasi yang saya dapatkan ketika ingin mendapatkan visibilitas ke apakah penyisipan atau pembaruan terjadi.
Definisi upsert_data
adalah untuk mengkonsolidasikan nilai menjadi satu sumber daya, daripada harus menentukan harga dan item_id dua kali: Sekali untuk pembaruan, sekali lagi untuk memasukkan.
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
Jika Anda tidak menyukai penggunaan upsert_data
, berikut ini adalah implementasi alternatif:
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