Insert or update. Upsert

Редактировал(а) Alexandr Fokin 2025/06/22 17:41

   
insert on conflict
If not exist
INSERT INTO table1
    (id)
SELECT 1
WHERE
   NOT EXISTS (
       SELECT 1
       FROM table1
       WHERE id = 1
       -- for share
   )
ON CONFLICT DO NOTHING
Избыточная генерация PK.

Конструкция ON CONFLICT не защищает от обращения к генератору ключа (sequence). И это может привести к тому, что счетчик будет крутиться впустую.
Использование выборки с условием вроде не убирает полностью ложные срабатывания (если они проходя одновременно), но после вставки записи, обращения к генератору прекратятся.

PostgreSQL Antipatterns: накручиваем себе проблемы
https://habr.com/ru/companies/tensor/articles/507688/

 Postgres: INSERT if does not exist already
https://stackoverflow.com/questions/4069718/postgres-insert-if-does-not-exist-already
Взаимодействие с блокировкамиПоведение параллельных транзакций (Read Commited):
Параллельные транзакцииselect for updateupdate или delete
Без where existsНе блокируется.Блокируется.
С where exsistsНе блокируетсяНе блокируется
с where exsists и for shareБлокируетсяБлокируется.

Важно подчеркнуть, select for update не всегда блокирует insert on conflict do nothing (как показано в таблице).
В некоторых случаях может потребоваться явное ручное обновление записи для блокировки, чтобы заблокировать параллельные вызовы upsert (чтобы они они дождались завершения текущей транзакции), причем в том числе возможно перед проверкой условий.

Merge Не ждет блокировок.
WITH upsert  

Внутренние ссылки:

Дочерние страницы:
Обратные ссылки:

Теги:
Создал(а) Alexandr Fokin 2024/02/03 19:11