0Pricing
SQL Academy · Урок

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 — локальная установка не требуется.

Все уроки этого курса

  1. INSERT с несколькими строками
  2. UPSERT: ON CONFLICT DO UPDATE (PostgreSQL)
  3. UPDATE с FROM и обновления в стиле JOIN
  4. DELETE с USING и безопасные шаблоны
← Назад к SQL Academy