带有WHERE子句的PostgreSQL Upsert

DaS*_*ode 2 sql postgresql unique upsert

我正在尝试将Oracle合并查询迁移到PostgreSql.正如在描述这个文章,Postgres的UPSERT语法支持"where子句"确定冲突的条件.

不幸的是,该网页没有提供"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)
Run Code Online (Sandbox Code Playgroud)

我希望我的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';
Run Code Online (Sandbox Code Playgroud)

这个例子有点做作,但我希望我能够在这里传达这个要点.

kli*_*lin 6

你需要一个部分索引.删除列上的uniqe约束并在列上name创建部分索引:

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');
Run Code Online (Sandbox Code Playgroud)

查询应如下所示:

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)    
Run Code Online (Sandbox Code Playgroud)

注意正确使用特殊记录excluded.每个文档:

ON CONFLICT DO UPDATE中的SET和WHERE子句可以使用表的名称(或别名)访问现有行,并使用特殊排除表访问建议插入的行.