Про 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)
Ханс-Юрген Шениг имеет опыт работы с PostgreSQL с 90-х годов. Он является генеральным директором и техническим руководителем компании CYBERTEC, которая является одним из лидеров рынка в этой области и с 2000 года обслуживает бесчисленное количество клиентов по всему миру.
Ещё раз ссылка на оригинал: PostgreSQL 15: Using MERGE in SQL
Leave a Reply