Перевод: CYBERTEC. PostgreSQL 15: Использование MERGE в SQL

PostgreSQLПро MERGE уже много говорилось. Поговорю и я путём перевода статьи от CyberTec.

Ссылка на оригинал: PostgreSQL 15: Using MERGE in SQL


Минуло уже много лет с тех пор, как появились первые идеи по реализации команды MERGE в майлинг-листах PostgreSQL [кое-что про MERGE писали и на хабре — «Битва при MERGE. Хроника с выводами и моралью»]. Прошло много лет и, наконец, эта важная функция вошла в ядро PostgreSQL. По состоянию дел на сегодня — она должна появиться в следующей, 15-й версии СУБД. Чтобы показать, как работает эта критически важная команда, я решил написать небольшой обзор работы этой замечательной команды. Она добавит много нового в PostgreSQL.

MERGE: Готовим данные

Как можно понять из названия, MERGE можно использовать для слияния списков и объединения их в один. Команда предоставляет простой способ добавления отсутствующих данных в список, при этом можно управлять поведением этого процесса и ещё многое другое.

Давайте подготовим данные для эксперимента:

db15=# CREATE TABLE t_test (
  id serial PRIMARY KEY,
  val int
);
CREATE TABLE
 
db15=# INSERT INTO t_test (val)
  SELECT x * 10 FROM generate_series(1, 10) AS x;
INSERT 0 10
 
db15=# SELECT * FROM t_test;
id | val
---+-----
1  | 10
2  | 20
3  | 30
4  | 40
5  | 50
6  | 60
7  | 70
8  | 80
9  | 90
10 | 100
(10 rows)

Здесь у нас создан список (таблица) из двух столбцов. Значения во втором столце в десять раз больше чем в первом. Это будет наша «целевая таблица», в которой нам нужно будет изменять данные.

Использование MERGE в PostgreSQL 15

Давайте запустим MERGE на наших данных и посмотрим что получится. Вот простой запрос:

db15=# MERGE INTO t_test
  USING (SELECT x, random() * 1000 AS z
  FROM generate_series(1, 16, 2) AS x
) AS y
ON t_test.id = y.x
WHEN MATCHED THEN
UPDATE SET val = z
WHEN NOT MATCHED THEN
INSERT (val) VALUES (z);
MERGE 8

Этот запрос будет менять данные в таблице t_test, с которой мы будем сливать поле «y», которое является результатом предложения USING. В предложении WHEN определяются правила, применяемые во время слияния. Когда у нас есть совпадение — мы перезаписываем существующее значение. Если значения нет — мы его добавим. Стоит акцентировать внимание на двух моментах: если внимательно посмотреть на UPDATE-часть запроса, мы увидим что целевая таблица нам больше не нужна. Что аналогично и для идущего далее INSERT’a — нам не нужно заново указывать таблицу t_test.

Как и ожидалось:

db15=# SELECT * FROM t_test ORDER BY id;
id | val
---+-----
1  | 101
2  | 20
3  | 656
4  | 40
5  | 309
6  | 60
7  | 897
8  | 80
9  | 195
10 | 100
11 | 634
12 | 625
13 | 50
(13 rows)

Мы видим что все нечетные идентификаторы оригинальных данных обновлены, а четные остались без изменений. И, естественно, добавлены недостающие строки.

Однако, это еще не всё: Мы можем использовать DELETE внутри MERGE:

db15=# MERGE INTO t_test
  USING (SELECT x, random() * 1000 AS z
FROM generate_series(1, 16, 2) AS x) AS y
ON t_test.id = y.x
WHEN MATCHED THEN
DELETE
WHEN NOT MATCHED THEN
INSERT (val) VALUES (z);
MERGE 8
db15=# SELECT * FROM t_test ORDER BY id;
id | val
---+-----
2  | 20
4  | 40
6  | 60
8  | 80
10 | 100
12 | 625
14 | 648
(7 rows)

В данном случае мы удалили все строки, в которых были найдены совпадения. DELETE не требует дополнительных аргументов. Так как ясно, какие строки будут обрабатываться — информация о колонке не нужна.

Заключение

MERGE — это ценная новая функция в PostgreSQL 15. Мы ждали много лет и вот, наконец-то, будет ещё проще работать с кодом.

Если вы хотите узнать больше о PostgreSQL и вам интересно, как PostgreSQL хранит функции и процедуры, ознакомьтесь с нашей статьей об этом.

Hans-Jürgen Schönig

Ханс-Юрген Шёниг (Hans-Jürgen Schönig)

Ханс-Юрген Шениг имеет опыт работы с PostgreSQL с 90-х годов. Он является генеральным директором и техническим руководителем компании CYBERTEC, которая является одним из лидеров рынка в этой области и с 2000 года обслуживает бесчисленное количество клиентов по всему миру.


Ещё раз ссылка на оригинал: PostgreSQL 15: Using MERGE in SQL


Be the first to comment

Leave a Reply

Ваш Mail не будет опубликован.


*