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();Связанные термины
Анекдоты по теме
Оптимизатор запросов говорит медленному подзапросу: — Ты почему тормозишь? — Я каждую строчку с каждой сравниваю через IN. — Используй EXISTS. — А я знаю, что я существую? — Вот поэтому ты и тормоз.
Разработчик смотрит на код коллеги: SELECT * FROM a, b WHERE a.id = b.a_id — Это что, неявный JOIN? — Синтаксис из 1992 года. — Оно работает? — Да. Но использовать — моветон.
— Зачем нужен RETURNING в PostgreSQL? — INSERT INTO users (name) VALUES ('Иван') RETURNING id; Возвращает id только что вставленной строки без дополнительного SELECT. — Удобно! — И для UPDATE: UPDATE users SET name='Пётр' WHERE id=1 RETURNING *;