Implementacja UPSERT jest niezwykle złożona, aby zapewnić ochronę przed równoczesnym dostępem do zapisu. Spójrz na tę Wiki Postgres, która służyła jako dziennik podczas początkowego tworzenia. Hakerzy Postgres postanowili nie uwzględniać „wykluczonych” wierszy w RETURNING
klauzula dotycząca pierwszego wydania w Postgres 9.5. Mogą coś wbudować w następne wydanie.
To jest kluczowe stwierdzenie w instrukcji, które wyjaśnia Twoją sytuację:
Składnia RETURNING
lista jest taka sama jak lista wyjściowa SELECT
. Zwrócone zostaną tylko wiersze, które zostały pomyślnie wstawione lub zaktualizowane. Na przykład, jeśli wiersz został zablokowany, ale nie został zaktualizowany, ponieważ ON CONFLICT DO UPDATE ... WHERE
warunek klauzuli nie został spełniony, wiersz nie zostanie zwrócony.
Pogrubiony nacisk na moje.
Dla pojedynczego wiersza do wstawienia:
Bez równoczesnego obciążenia zapisu na tej samej tabeli
WITH ins AS (
INSERT INTO users(name)
VALUES ('new_usr_name') -- input value
ON CONFLICT(name) DO NOTHING
RETURNING users.id
)
SELECT id FROM ins
UNION ALL
SELECT id FROM users -- 2nd SELECT never executed if INSERT successful
WHERE name = 'new_usr_name' -- input value a 2nd time
LIMIT 1;
Z możliwym równoczesnym obciążeniem zapisu na stole
Rozważ to zamiast tego (dla pojedynczego wiersza INSERT
):
- Czy SELECT lub INSERT w funkcji podatnej na wyścigi?
Aby wstawić zestaw wierszy :
-
Jak używać RETURNING z ON CONFLICT w PostgreSQL?
-
Jak uwzględnić wykluczone wiersze w RETURNING z INSERT ... ON CONFLICT
Wszystkie trzy z bardzo szczegółowym wyjaśnieniem.