De implementatie van UPSERT is enorm complex om veilig te zijn tegen gelijktijdige schrijftoegang. Kijk eens naar deze Postgres Wiki die tijdens de eerste ontwikkeling als log diende. De Postgres-hackers hebben besloten geen "uitgesloten" rijen op te nemen in de RETURNING
clausule voor de eerste release in Postgres 9.5. Misschien bouwen ze iets in voor de volgende release.
Dit is de cruciale verklaring in de handleiding om uw situatie uit te leggen:
De syntaxis van de
RETURNING
lijst is identiek aan die van de uitvoerlijst vanSELECT
. Alleen rijen die met succes zijn ingevoegd of bijgewerkt, worden geretourneerd. Als een rij bijvoorbeeld is vergrendeld maar niet is bijgewerkt omdat eenON CONFLICT DO UPDATE ... WHERE
clausule voorwaarde was niet voldaan, de rij wordt niet geretourneerd.
Vetgedrukte nadruk van mij.
Voor een enkele rij invoegen:
Zonder gelijktijdige schrijfbelasting op dezelfde tafel
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;
Met mogelijke gelijktijdige schrijfbelasting op de tafel
Overweeg dit in plaats daarvan (voor enkele rij INSERT
):
- Is SELECT of INSERT in een functie die vatbaar is voor race-omstandigheden?
Een set rijen invoegen :
-
Hoe RETURNING gebruiken met ON CONFLICT in PostgreSQL?
-
Uitgesloten rijen opnemen in RETURNING from INSERT ... ON CONFLICT
Alle drie met zeer gedetailleerde uitleg.