Написать пост

Применение оператора MERGE в PostgreSQL

Аватарка пользователя Slava Rozhnev

Рассмотрим, как использовать оператор MERGE в PostgreSQL для эффективного выполнения операций INSERT, UPDATE или DELETE строк в таблице

Оператор 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 <condition>
WHEN MATCHED THEN
    <update_statement>
WHEN NOT MATCHED THEN
    <insert_statement>
		

Здесь 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
;
		

Здесь можно выполнить SQL-запрос.

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

Если Вам понравилась статья, Вы можете поддержать автора.

Следите за новыми постами
Следите за новыми постами по любимым темам
4К открытий4К показов