PostgreSQLСредний
UPSERT (ON CONFLICT)
Вставляет строку или обновляет её при конфликте уникального ключа. Атомарная операция.
Синтаксис
INSERT INTO table (cols) VALUES (...) ON CONFLICT (unique_col) DO UPDATE SET col = EXCLUDED.col;
Объяснение
UPSERT = INSERT + UPDATE при конфликте. В PostgreSQL: ON CONFLICT DO UPDATE или ON CONFLICT DO NOTHING.
Атомарен — нет race condition между проверкой и вставкой. Безопаснее, чем проверять через SELECT + INSERT/UPDATE в приложении.
Пример
-- Атомарный счётчик
INSERT INTO page_views (page, views) VALUES ('home', 1)
ON CONFLICT (page) DO UPDATE
SET views = page_views.views + 1;
-- Обновить профиль или создать
INSERT INTO profiles (user_id, bio) VALUES ($1, $2)
ON CONFLICT (user_id) DO UPDATE
SET bio = EXCLUDED.bio, updated_at = NOW();Связанные термины
Анекдоты по теме
— Что такое «потерянное обновление»? — Две транзакции читают одно значение, обе его изменяют, одно изменение теряется. — Пример? — Оба читают balance=100. Оба делают balance-10. Оба пишут 90. Должно быть 80. — Решение? — UPDATE balance = balance - 10 — атомарно. — Или SELECT FOR UPDATE. — Или SERIALIZABLE.
— Почему оконные функции не ходят на свидания вслепую? — Потому что им нужно знать OVER (PARTITION BY кто_пришёл ORDER BY красота DESC), иначе они не знают, как себя вести.
DBA объясняет жене: — Дорогая, я как FOREIGN KEY. Я всегда ссылаюсь на тебя — мою PRIMARY KEY. Жена: — А если я удалюсь? DBA: — Тогда я не смогу существовать. Будет ошибка.