MERGE
MERGE сопоставляет источник с целевой таблицей и выполняет разные действия для совпавших и несовпавших строк. Точный синтаксис и конкурентные гарантии заметно различаются между СУБД.
MERGE INTO user_totals AS target
USING daily_totals AS source
ON target.user_id = source.user_id
WHEN MATCHED THEN
UPDATE SET total = source.total
WHEN NOT MATCHED THEN
INSERT (user_id, total)
VALUES (source.user_id, source.total);Для чего подходит
- синхронизация staging-таблицы с основной;
- пакетное обновление и вставка;
- загрузка подготовленной проекции;
- описание нескольких ветвей обработки одним оператором.
Это не универсальная идемпотентность
Повтор операции безопасен только если бизнес-ключ, исходные данные и действия спроектированы для повтора. MERGE сам по себе не защищает от двойного внешнего эффекта.
Конкуренция
Две сессии могут одновременно решить, что строки нет, и попытаться вставить ее. Нужны:
UNIQUEна ключе сопоставления;- понимание блокировок конкретной СУБД;
- обработка конфликта/retry;
- иногда специальный UPSERT (
INSERT ... ON CONFLICT,ON DUPLICATE KEY) вместоMERGE.
Ловушки
- Несколько строк источника, совпавших с одной строкой цели, могут вызвать ошибку или неоднозначное поведение.
- Условие
ONдолжно совпадать с реальным ключом, иначе обновится не та гранулярность. - Триггеры и порядок ветвей зависят от реализации.
- Нельзя переносить пример между диалектами без проверки.
Связано: Ограничения, constraints, Ключи БД, Транзакции принцип ACID.
Вопросы
Чем MERGE отличается от UPDATE? Он умеет выбирать действие в зависимости от наличия сопоставленной строки.
Нужен ли UNIQUE при upsert? Да, именно ограничение является последней защитой уникальности при конкуренции.
Гарантирует ли MERGE отсутствие гонок? Не автоматически; гарантии зависят от СУБД, индексов и уровня изоляции.