如何使用 PostgreSQL Upsert 在不同的 where 条件下使用 INSERT ON CONFLICT 语句更新多列
How to do multiple columns update on different where condition using PostgreSQL Upsert Using INSERT ON CONFLICT statement
假设我有一个像这样的 table
create schema test;
CREATE TABLE test.customers (
customer_id serial PRIMARY KEY,
name VARCHAR UNIQUE,
email VARCHAR NOT NULL,
active bool NOT NULL DEFAULT TRUE,
is_active_datetime TIMESTAMP(3) NOT NULL DEFAULT'1900-01-01T00:00:00.000Z'::timestamp(3)
updated_datetime TIMESTAMP(3) NOT NULL DEFAULT '1900-01-01T00:00:00.000Z'::timestamp(3),
);
现在如果我想更新 email
冲突 name
WHERE $tableName.updated_datetime < excluded.updated_datetime
我想在冲突 name
上更新 is_active_datetime
,但此更新的条件是活动标志已更改。
WHERE customer.active != excluded.active
基本上想跟踪活动状态何时更改。所以我可以在这样的单个语句中做到这一点
初始插入:
insert INTO test.customers (NAME, email)
VALUES
('IBM', 'contact@ibm.com'),
(
'Microsoft',
'contact@microsoft.com'
),
(
'Intel',
'contact@intel.com'
);
为了实现我的目的,我正在尝试这样的事情:
select * from test.customers;
INSERT INTO customers (name, email)
VALUES
(
'Microsoft',
'hotline@microsoft.com'
)
ON CONFLICT (name)
DO
UPDATE
SET customers.email = EXCLUDED.email
WHERE $tableName.updated_datetime < excluded.updated_datetime
on CONFLICT (name)
do
update
set is_active_datetime = current_timestamp()
WHERE customer.active != excluded.active ;
这可以吗?如何使用此方法执行此操作。
您可以在单个 DO UPDATE clause
中使用 CASE
条件更新多个列。
INSERT INTO customers (
name
,email
,updated_datetime
)
VALUES (
'Microsoft'
,'hotline@microsoft.com'
,now()
) ON CONFLICT(name) DO
UPDATE
SET email = CASE
WHEN customers.updated_datetime < excluded.updated_datetime
THEN excluded.email
ELSE customers.email --default when condition not satisfied
END
,is_active_datetime = CASE
WHEN customers.active != excluded.active
THEN current_timestamp
ELSE customers.is_active_datetime
END;
假设我有一个像这样的 table
create schema test;
CREATE TABLE test.customers (
customer_id serial PRIMARY KEY,
name VARCHAR UNIQUE,
email VARCHAR NOT NULL,
active bool NOT NULL DEFAULT TRUE,
is_active_datetime TIMESTAMP(3) NOT NULL DEFAULT'1900-01-01T00:00:00.000Z'::timestamp(3)
updated_datetime TIMESTAMP(3) NOT NULL DEFAULT '1900-01-01T00:00:00.000Z'::timestamp(3),
);
现在如果我想更新 email
冲突 name
WHERE $tableName.updated_datetime < excluded.updated_datetime
我想在冲突 name
上更新 is_active_datetime
,但此更新的条件是活动标志已更改。
WHERE customer.active != excluded.active
基本上想跟踪活动状态何时更改。所以我可以在这样的单个语句中做到这一点
初始插入:
insert INTO test.customers (NAME, email)
VALUES
('IBM', 'contact@ibm.com'),
(
'Microsoft',
'contact@microsoft.com'
),
(
'Intel',
'contact@intel.com'
);
为了实现我的目的,我正在尝试这样的事情:
select * from test.customers;
INSERT INTO customers (name, email)
VALUES
(
'Microsoft',
'hotline@microsoft.com'
)
ON CONFLICT (name)
DO
UPDATE
SET customers.email = EXCLUDED.email
WHERE $tableName.updated_datetime < excluded.updated_datetime
on CONFLICT (name)
do
update
set is_active_datetime = current_timestamp()
WHERE customer.active != excluded.active ;
这可以吗?如何使用此方法执行此操作。
您可以在单个 DO UPDATE clause
中使用 CASE
条件更新多个列。
INSERT INTO customers (
name
,email
,updated_datetime
)
VALUES (
'Microsoft'
,'hotline@microsoft.com'
,now()
) ON CONFLICT(name) DO
UPDATE
SET email = CASE
WHEN customers.updated_datetime < excluded.updated_datetime
THEN excluded.email
ELSE customers.email --default when condition not satisfied
END
,is_active_datetime = CASE
WHEN customers.active != excluded.active
THEN current_timestamp
ELSE customers.is_active_datetime
END;