PostgreSQL Upsert with a WHERE clause



我正在尝试将Oracle合并查询迁移到PostgreSQL。如本文所述,Postgres UpSert语法支持" Were rales"以确定冲突条件。

不幸的是,该网页没有提供" Where子句"的示例。我尝试在其他地方搜索它,但找不到它。因此这个问题。

按照以上给定的网页中的同一示例,这是一个示例设置:

CREATE TABLE customers (
    customer_id serial PRIMARY KEY,
    name VARCHAR UNIQUE,
    email VARCHAR NOT NULL,
    active bool NOT NULL DEFAULT TRUE
);
INSERT INTO customers (NAME, email) VALUES
 ('IBM', 'contact@ibm.com'),
 ('Microsoft', 'contact@microsoft.com'),
 ('Intel','contact@intel.com');

SELECT * FROM customers;
 customer_id |   name    |         email         | active
-------------+-----------+-----------------------+--------
           1 | IBM       | contact@ibm.com       | t
           2 | Microsoft | contact@microsoft.com | t
           3 | Intel     | contact@intel.com     | t
(3 rows)

我希望我的UpSert语句看起来像这样:

INSERT INTO customers (NAME, email)
VALUES
('Microsoft', 'hotline@microsoft.com') 
ON CONFLICT where (name = 'Microsoft' and active = TRUE)
DO UPDATE SET email = 'hotline@microsoft.com';

这个示例有点人为,但我希望我能够在这里传达要点。

您需要部分索引。在name列上删除Uniqe约束,并在列上创建部分索引:

CREATE TABLE customers (
    customer_id serial PRIMARY KEY,
    name VARCHAR,
    email VARCHAR NOT NULL,
    active bool NOT NULL DEFAULT TRUE
);
CREATE UNIQUE INDEX ON customers (name) WHERE active;
INSERT INTO customers (NAME, email) VALUES
 ('IBM', 'contact@ibm.com'),
 ('Microsoft', 'contact@microsoft.com'),
 ('Intel','contact@intel.com');

查询应该看起来像这样:

INSERT INTO customers (name, email)
VALUES
    ('Microsoft', 'hotline@microsoft.com') 
ON CONFLICT (name) WHERE active
DO UPDATE SET email = excluded.email;
SELECT *
FROM customers;
 customer_id |   name    |         email         | active 
-------------+-----------+-----------------------+--------
           1 | IBM       | contact@ibm.com       | t
           3 | Intel     | contact@intel.com     | t
           2 | Microsoft | hotline@microsoft.com | t
(3 rows)    

请注意,根据文档正确使用特殊记录excluded.

"集合"one_answers"在冲突中"的位置更新可以使用表的名称(或别名)访问现有行,以及使用Special 排除的表插入建议的行。

最新更新