L'implementazione di UPSERT è estremamente complessa per essere protetta dall'accesso simultaneo in scrittura. Dai un'occhiata a questo Wiki di Postgres che è servito da registro durante lo sviluppo iniziale. Gli hacker di Postgres hanno deciso di non includere le righe "escluse" nel RETURNING
clausola per il primo rilascio in Postgres 9.5. Potrebbero creare qualcosa per la prossima versione.
Questa è l'affermazione cruciale nel manuale per spiegare la tua situazione:
La sintassi del RETURNING
list è identico a quello dell'outputlist di SELECT
. Verranno restituite solo le righe che sono state inserite o aggiornate correttamente. Ad esempio, se una riga è stata bloccata ma non aggiornata perché un ON CONFLICT DO UPDATE ... WHERE
la condizione della clausola non è stata soddisfatta, la riga non verrà restituita.
Enfasi in grassetto la mia.
Per una riga singola per inserire:
Senza carico di scrittura simultaneo sulla stessa tabella
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;
Con possibile carico di scrittura simultaneo sulla tabella
Considera questo invece (per riga singola INSERT
):
- SELEZIONA o INSERT in una funzione soggetta a condizioni di gara?
Per inserire un insieme di righe :
-
Come utilizzare RETURNING con ON CONFLICT in PostgreSQL?
-
Come includere le righe escluse in RETURNING from INSERT ... ON CONFLICT
Tutti e tre con una spiegazione molto dettagliata.