Статья основана на 19 видео из 30 тем курса SQL c 0 от Аристова Евгения. Ссылки на видео на платформах RUTUBE и VK видео.
MERGE vs INSERT ON CONFLICT
MERGE появился в PostgreSQL только в 14 версии
MERGE похож на оператор UPSERT в других диалектах SQL или INSERT ON CONFLICT (подробнее о его синтаксисе в моей статье) в PostgreSQL.
MERGE имеет ряд преимуществ:
- Более эффективен, поскольку выполняет только необходимые операции для каждой строки.
- Атомарный, поскольку либо успешно выполняется, либо завершается неудачей целиком.
- Более гибкий, поскольку позволяет указывать более сложные условия.
Синтаксис
Синтаксис MERGE:
MERGE INTO target_table AS t
USING source_table AS s
ON 'condition'
WHEN MATCHED THEN
'update_statement'
WHEN NOT MATCHED THEN
'insert_statement'
Классическое использование – дополнение данных в целевой таблице с помощью таблицы-источника. Используется, когда требуется не мгновенное изменение данных, а немного отложенное.
Практика
Создадим таблицу с аккаунтами:
CREATE TABLE customer_account(
id SERIAL,
fk_customer INT NOT NULL,
balance NUMERIC(15,2)
);
Заполняем тремя значениями:
INSERT INTO customer_account (fk_customer,balance) VALUES
(1, 100.0),
(2,200.5),
(3,300.9);
Создадим таблицу с транзакциями:
CREATE TABLE recent_transactions(
id SERIAL,
fk_customer INT NOT NULL,
transaction_value NUMERIC(15,2)
);
Добавим транзакции в таблицу:
INSERT INTO recent_transactions (fk_customer,transaction_value)
VALUES
(1, -10.0),
(2,10.0);
INSERT INTO recent_transactions (fk_customer,transaction_value)
VALUES
(5,500.0);
В таблицу с транзакциями добавлен пользователь, которого нет в таблице аккаунтов.
Напишем команду, которая в таблице Аккаунты (целевая) при совпадении внешнего ключа обновляет баланс в соответствие с таблицей Транзакции (таблица-источник), а при не совпадении внешнего ключа – добавляет пользователя и баланс:
MERGE INTO customer_account ca
USING recent_transactions t
ON t.fk_customer = ca.fk_customer
WHEN MATCHED THEN
UPDATE SET balance = balance + t.transaction_value
WHEN NOT MATCHED THEN
INSERT (fk_customer, balance) VALUES
(t.fk_customer, t.transaction_value);
Презентация к статье здесь.
20 из 30 тем будет скоро доступна. Если вы хотите быстрее получить доступ – присоединяйтесь к онлайн группе, ссылка доступна в описании курса.
Добавить комментарий