UPSERT-implementeringen är enormt komplex för att vara säker mot samtidig skrivåtkomst. Ta en titt på denna Postgres Wiki som fungerade som logg under den initiala utvecklingen. Postgres hackare beslutade att inte inkludera "uteslutna" rader i RETURNING
klausul för den första utgåvan i Postgres 9.5. De kanske bygger in något för nästa utgåva.
Detta är det avgörande uttalandet i manualen för att förklara din situation:
Syntaxen för
RETURNING
listan är identisk med den för utdatalistan förSELECT
. Endast rader som har infogats eller uppdaterats kommer att returneras. Till exempel, om en rad var låst men inte uppdaterad eftersom enON CONFLICT DO UPDATE ... WHERE
klausulens villkor var inte uppfyllt, raden kommer inte att returneras.
Djärv betoning min.
För en en rad att infoga:
Utan samtidig skrivbelastning på samma tabell
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;
Med möjlig samtidig skrivbelastning på tabellen
Överväg detta istället (för en rad INSERT
):
- Är SELECT eller INSERT i en funktion utsatt för tävlingsförhållanden?
För att infoga en uppsättning rader :
-
Hur använder man RETURNING med ON CONFLICT i PostgreSQL?
-
Hur man inkluderar exkluderade rader i RETURNING from INSERT ... ON CONFLICT
Alla tre med mycket detaljerad förklaring.