PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Rufen Sie die ID von einem bedingten INSERT ab

Die UPSERT-Implementierung ist enorm komplex, um gegen gleichzeitige Schreibzugriffe sicher zu sein. Werfen Sie einen Blick auf dieses Postgres-Wiki, das während der anfänglichen Entwicklung als Protokoll diente. Die Postgres-Hacker haben entschieden, "ausgeschlossene" Zeilen nicht in RETURNING aufzunehmen -Klausel für die erste Version in Postgres 9.5. Sie könnten etwas für die nächste Version einbauen.

Dies ist die entscheidende Aussage im Handbuch, um Ihre Situation zu erklären:

Die Syntax von RETURNING list ist identisch mit der Ausgabeliste von SELECT . Nur Zeilen, die erfolgreich eingefügt oder aktualisiert wurden, werden zurückgegeben. Zum Beispiel, wenn eine Zeile gesperrt, aber nicht aktualisiert wurde, weil ein ON CONFLICT DO UPDATE ... WHERE Klauselbedingung nicht erfüllt, wird die Zeile nicht zurückgegeben.

Fettdruck von mir.

Für eine einzelne Zeile einfügen:

Ohne gleichzeitige Schreiblast auf derselben Tabelle

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;

Mit möglicher gleichzeitiger Schreiblast auf der Tabelle

Ziehen Sie stattdessen Folgendes in Betracht (für einzelne Zeile INSERT ):

  • Ist SELECT oder INSERT in einer Funktion anfällig für Race-Conditions?

Zum Einfügen eines Satzes von Zeilen :

  • Wie verwendet man RETURNING mit ON CONFLICT in PostgreSQL?

  • So schließen Sie ausgeschlossene Zeilen in RETURNING von INSERT ... ON CONFLICT ein

Alle drei mit sehr ausführlicher Erklärung.