MERGE в PostgreSQL

Статья основана на 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 тем будет скоро доступна. Если вы хотите быстрее получить доступ – присоединяйтесь к онлайн группе, ссылка доступна в описании курса.

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

семь + 10 =