Оператор MERGE — это мощный инструмент, который можно использовать для выполнения условных операций INSERT, UPDATE или DELETE строк в таблице. Он был введен в стандарте SQL:2003 и расширен в стандарте SQL:2008.
В этой статье мы рассмотрим, как использовать оператор MERGE в PostgreSQL для эффективного выполнения этих операций.
MERGE похож на оператор UPSERT в других диалектах SQL, но имеет ряд преимуществ, включая:
- Он более эффективен, поскольку выполняет только необходимые операции для каждой строки.
- Он атомарный, поскольку либо успешно выполняется, либо завершается неудачей целиком.
- Он более гибкий, поскольку позволяет указывать более сложные условия.
В PostgreSQL до версии 15 для условных операций INSERT, UPDATE и DELETE можно было использовать оператор INSERT INTO ... ON CONFLICT [ conflict_target ] conflict_action. Однако, начиная с версии 15, появилась возможность использовать все преимущества оператора MERGE.
Синтаксис оператора MERGE выглядит следующим образом:
MERGE INTO target_table AS t USING source_table AS s ON
Здесь target_table — это таблица, которую нужно обновить или в которую нужно вставить строки.
source_table — это таблица, содержащая данные, которые будут использоваться для обновления или вставки строк в target_table.
Условие — это логическое выражение, используемое для определения, нужно ли обновлять или вставлять строку из source_table.
update_statement — это SQL-запрос, используемый для обновления строк в target_table.
insert_statement — это SQL-запрос, используемый для вставки строк в target_table.
Вот пример оператора MERGE, который обновляет таблицу customers, используя таблицу leads. Обе таблицы имеют поле email, поэтому нам нужно добавлять только те строки из leads, email которых не существует в таблице customers:
MERGE INTO customers AS c USING leads AS l ON c.email = l.email WHEN NOT MATCHED THEN insert (name, email, created_at) VALUES (l.name, l.email, DEFAULT);
Для каждой строки, для которой не нет соответствия, будет выполнен запрос на вставку.
Этот запрос эквивалентен следующему запросу UPSERT:
INSERT INTO customers (name, email) SELECT name, email FROM leads ON conflict (email) DO nothing;
Но, если мы посмотрим на результаты, мы увидим преимущество оператора MERGE: он не увеличивает поле id в случае, если запись уже существует. Здесь можно выполнить тест SQL.
Давайте попробуем выполнить более сложную задачу. Теперь мы добавим новые записи в таблицу customers с новыми электронными адресами и обновим имя для уже существующих записей.
MERGE INTO customers AS c USING leads AS l ON c.email = l.email WHEN NOT MATCHED THEN INSERT (name, email, created_at) VALUES (l.name, l.email, DEFAULT) WHEN MATCHED THEN UPDATE SET name = l.name ;
А в последнем сценарии мы добавим записи в таблицу customers с отсутствующими электронными адресами, обновим имя, если дата создания клиента меньше, чем соответствующая дата в leads, и удалим другие записи:
MERGE INTO customers AS c USING leads AS l ON c.email = l.email WHEN NOT MATCHED THEN INSERT (name, email, created_at) VALUES (l.email, l.name, DEFAULT) WHEN MATCHED AND c.created_at < l.created_at THEN UPDATE SET name = l.name WHEN MATCHED THEN DELETE ;
Таким образом мы познакомились с командой MERGE, которая позволяет выполнять условные операции INSERT, UPDATE или DELETE на строках таблицы. Этот инструмент более эффективен, атомарен и гибок, чем другие SQL-диалекты.
Благодаря MERGE можно выполнять более сложные задачи, связанные с обновлением и вставкой данных в таблицы.
Следите за новыми постами по любимым темам
Подпишитесь на интересующие вас теги, чтобы следить за новыми постами и быть в курсе событий.