Implementace UPSERT je nesmírně složitá, aby byla bezpečná proti souběžnému přístupu pro zápis. Podívejte se na tuto Postgres Wiki, která sloužila jako log během počátečního vývoje. Hackeři Postgres se rozhodli nezahrnout „vyloučené“ řádky do RETURNING
klauzule pro první vydání v Postgres 9.5. Mohli by něco zabudovat do příštího vydání.
Toto je klíčové prohlášení v příručce pro vysvětlení vaší situace:
Syntaxe
RETURNING
seznam je identický s výstupním seznamemSELECT
. Vrátí se pouze řádky, které byly úspěšně vloženy nebo aktualizovány. Pokud byl například řádek uzamčen, ale nebyl aktualizován, protožeON CONFLICT DO UPDATE ... WHERE
podmínka klauzule nebyla splněna, řádek nebude vrácen.
Tučné zdůraznění moje.
Pro jeden řádek vložit:
Bez souběžného zatížení zápisu na stejnou tabulku
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;
S možným souběžným zatížením zápisu na stůl
Místo toho zvažte toto (pro jeden řádek INSERT
):
- Je SELECT nebo INSERT ve funkci náchylný k závodům?
Chcete-li vložit množinu řádků :
-
Jak používat RETURNING s ON CONFLICT v PostgreSQL?
-
Jak zahrnout vyloučené řádky do RETURNING from INSERT ... ON CONFLICT
Všechny tři s velmi podrobným vysvětlením.