Как выполнить обновление нескольких столбцов в разных условиях, используя PostgreSQL Upsert, используя инструкцию INSERT ON CONFLICT - PullRequest
0 голосов
/ 02 февраля 2019

Предположим, у меня есть такая таблица

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

, и я хочу обновить is_active_datetimeпри конфликте name, но это условие для этого обновления, где активный флаг изменился.

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 ;

Этоможно это сделать?Как это сделать с помощью этого метода.

1 Ответ

0 голосов
/ 02 февраля 2019

Вы можете обновить несколько столбцов с условиями CASE в одном DO UPDATE clause.

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;

Демо

...