CẬP NHẬT (2015-08-20):
Bây giờ có một thi chính thức để xử lý upserts thông qua việc sử dụng ON CONFLICT DO UPDATE(tài liệu chính thức). Tại thời điểm viết bài này, tính năng này hiện đang nằm trong PostgreSQL 9.5 Alpha 2, có sẵn để tải xuống tại đây: Thư mục nguồn Postgres .
Đây là một ví dụ, giả sử item_idlà Khóa chính của bạn:
INSERT INTO my_table
    (item_id, price)
VALUES
    (123456, 10.99)
ON
    CONFLICT (item_id)
DO UPDATE SET
    price = EXCLUDED.price
Bài gốc ...
Đây là một triển khai tôi đã thực hiện khi mong muốn đạt được khả năng hiển thị về việc liệu có chèn hoặc cập nhật hay không.
Định nghĩa của upsert_datalà hợp nhất các giá trị thành một tài nguyên duy nhất, thay vì phải chỉ định giá và item_id hai lần: Một lần cho bản cập nhật, một lần nữa cho phần chèn.
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
Nếu bạn không thích sử dụng upsert_data, đây là một triển khai thay thế:
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