UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)
Реализуйте идемпотентную вставку с помощью ON CONFLICT DO UPDATE, используйте EXCLUDED и выбирайте правильную цель конфликта
«UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)» — бесплатный урок SQL Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.
Что такое UPSERT?
UPSERT = INSERT, если строки не существует, и UPDATE, если она уже есть. В PostgreSQL это записывается как INSERT ... ON CONFLICT.
ON CONFLICT DO NOTHING
Вставить, если строки нет, и молча пропустить операцию при дубликате:
INSERT INTO users (email, full_name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email) DO NOTHING;ON CONFLICT DO UPDATE
Вставить, если строки нет, иначе обновить определённые столбцы:
INSERT INTO users (email, full_name, last_login)
VALUES ('alice@example.com', 'Alice', NOW())
ON CONFLICT (email)
DO UPDATE SET
full_name = EXCLUDED.full_name,
last_login = EXCLUDED.last_login;EXCLUDED: предлагаемая строка
Внутри DO UPDATE выражение EXCLUDED.col означает «значение, которое пытался вставить INSERT». Простое имя столбца (или users.col) означает значение существующей строки.
ON CONFLICT (email)
DO UPDATE SET visits = users.visits + 1,
last_seen = EXCLUDED.last_seen;Цель конфликта
Необходимо указать ограничение уникальности или первичный ключ:
ON CONFLICT (email) -- column with UNIQUE
ON CONFLICT (user_id, day) -- composite UNIQUE
ON CONFLICT ON CONSTRAINT users_email_key -- by nameУсловный UPSERT (WHERE в DO UPDATE)
Обновлять только при выполнении условия:
INSERT INTO inventory (product_id, qty)
VALUES (42, 5)
ON CONFLICT (product_id)
DO UPDATE SET qty = inventory.qty + EXCLUDED.qty
WHERE inventory.qty + EXCLUDED.qty <= 1000;Многострочный UPSERT
Вставить много строк; каждая строка обрабатывается отдельно:
INSERT INTO page_views (path, day, count)
VALUES ('/home', CURRENT_DATE, 1), ('/about', CURRENT_DATE, 1)
ON CONFLICT (path, day)
DO UPDATE SET count = page_views.count + EXCLUDED.count;RETURNING с UPSERT
Получить итоговую строку — независимо от того, была ли она вставлена или обновлена:
INSERT INTO users (email, full_name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email) DO UPDATE
SET full_name = EXCLUDED.full_name
RETURNING id, full_name;Идемпотентные рабочие процессы
UPSERT делает повторные попытки безопасными. Если ваш веб-хук сработает дважды, второй вызов обновит ту же строку, а не создаст дубликат.
MERGE (стандарт SQL, PG15+)
В PostgreSQL 15 появился соответствующий стандарту SQL MERGE, который позволяет выполнить INSERT/UPDATE/DELETE в одном операторе:
MERGE INTO users AS u
USING (VALUES ('alice@example.com','Alice')) AS src(email, name)
ON u.email = src.email
WHEN MATCHED THEN UPDATE SET full_name = src.name
WHEN NOT MATCHED THEN INSERT (email, full_name) VALUES (src.email, src.name);Когда не следует использовать UPSERT
Для UPSERT требуется ограничение уникальности. Если его нет, обычно нужен отдельный SELECT, а затем INSERT или UPDATE — но помните о состоянии гонки: заключите операции в транзакцию с подходящей блокировкой.
Итоги
ON CONFLICT — это чистый и атомарный UPSERT в PostgreSQL.
- DO NOTHING — чтобы «вставить, если строки нет»
- DO UPDATE — для полноценного UPSERT
EXCLUDED= предлагаемая строка- Всегда указывайте цель конфликта
Быстрая проверка
В выражении ON CONFLICT (email) DO UPDATE SET last_login = EXCLUDED.last_login что обозначает EXCLUDED?
Часто задаваемые вопросы
Урок «UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)» бесплатный?
Да — полный текст урока «UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.
Чему я научусь в уроке «UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)»?
Реализуйте идемпотентную вставку с помощью ON CONFLICT DO UPDATE, используйте EXCLUDED и выбирайте правильную цель конфликта Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Academy?
Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Academy?
Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- INSERT с несколькими строками
- UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)
- UPDATE с FROM и обновления в стиле JOIN
- DELETE с USING и безопасные шаблоны