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();Связанные термины
INSERTДобавляет новые строки в таблицу.MERGEСтандартная SQL-команда «вставить или обновить» — сравнивает исходные данные с целевой таблицей и выполняет INSERT/UPDATE/DELETE в одном запросе.PRIMARY KEYУникальный идентификатор строки. Автоматически создаёт уникальный индекс, не допускает NULL.RETURNINGВозвращает строки после INSERT, UPDATE или DELETE без дополнительного SELECT.Транзакция (TRANSACTION)Группа SQL операций, выполняемых как единое целое: либо все успешно, либо ни одна.
Анекдоты по теме
— Почему PRIMARY KEY не может быть NULL? — Потому что паспорт без номера — это не паспорт. «Я есть, но кто я — неизвестно» — так не работает.
— Чем VARCHAR(255) отличается от TEXT? — В PostgreSQL — почти ничем по производительности. — Тогда зачем VARCHAR(255)? — Традиция. И ограничение длины, если оно нужно.
— Почему запрос SELECT * FROM users чувствует себя неуверенно? — Потому что он не знает, кого именно из себя изображать. Всех и сразу — это непрофессионально.