UPSERT-implementeringen er enormt kompleks for at være sikker mod samtidig skriveadgang. Tag et kig på denne Postgres Wiki, der fungerede som log under den indledende udvikling. Postgres-hackerne besluttede ikke at inkludere "udelukkede" rækker i RETURNING
klausul for den første udgivelse i Postgres 9.5. De kan måske bygge noget ind til den næste udgivelse.
Dette er den afgørende erklæring i manualen for at forklare din situation:
Syntaksen for RETURNING
listen er identisk med outputlisten for SELECT
. Kun rækker, der blev indsat eller opdateret, returneres. For eksempel, hvis en række var låst, men ikke opdateret, fordi en ON CONFLICT DO UPDATE ... WHERE
klausulens betingelse var ikke opfyldt, rækken vil ikke blive returneret.
Fed fremhævelse mine.
For en enkelt række at indsætte:
Uden samtidig skrivebelastning på den samme tabel
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 mulig samtidig skrivebelastning på bordet
Overvej dette i stedet (for enkelt række INSERT
):
- Er SELECT eller INSERT i en funktion, der er tilbøjelig til løbsforhold?
For at indsætte et sæt rækker :
-
Hvordan bruger man RETURNING med ON CONFLICT i PostgreSQL?
-
Sådan inkluderes ekskluderede rækker i RETURNING from INSERT ... ON CONFLICT
Alle tre med meget detaljeret forklaring.