Geben Sie die ID zurück, wenn eine Zeile existiert, INSERT andernfalls

8

Ich schreibe eine Funktion in node.js, um eine PostgreSQL-Tabelle abzufragen.
Wenn die Zeile vorhanden ist, möchte ich die ID-Spalte aus der Zeile zurückgeben.
Wenn es nicht existiert, möchte ich es einfügen und die ID ( insert into ... returning id ) zurückgeben.

Ich habe versucht, Variationen von case und if else -Anweisungen zu versuchen und es scheint nicht zu funktionieren.

    
Jared 07.04.2012, 19:33
quelle

4 Antworten

7

Ich würde vorschlagen, die Überprüfung auf der Datenbankseite durchzuführen und die ID nur an nodejs zurückzugeben.

Beispiel:

%Vor%

Und dann auf der Node.js-Seite (in diesem Beispiel verwende ich node-postgres):

%Vor%     
Viehzeug 07.04.2012, 20:28
quelle
9

Eine Lösung in einer einzelnen SQL-Anweisung. Benötigt PostgreSQL 8.4 oder später.
Betrachten Sie die folgende Demo:

Testeinrichtung:

%Vor%

INSERT / SELECT-Befehl:

%Vor%
  • Der erste CTE v ist nicht unbedingt erforderlich, aber Sie müssen Ihre Werte nur einmal eingeben.

  • Der zweite CTE s wählt das id von tbl aus, wenn die "Zeile" existiert.

  • Der dritte CTE i fügt die "row" in tbl ein, wenn (und nur wenn) es nicht existiert und id zurückgibt.

  • Der letzte SELECT gibt den id zurück. Ich fügte eine Spalte src hinzu, die die "Quelle" angibt - ob die "Zeile" bereits existierte und id von einem SELECT kam, oder die "Zeile" war neu und das ist auch id .

  • Diese Version sollte so schnell wie möglich sein, da sie kein zusätzliches SELECT von tbl benötigt und stattdessen die CTEs verwendet.

Um dies vor möglichen Rennbedingungen in einer Mehrbenutzerumgebung zu schützen:
Auch für aktualisierte Techniken, die den neuen UPSERT in Postgres 9.5 oder später verwenden:

Erwin Brandstetter 09.04.2012 20:53
quelle
2

So etwas, wenn Sie auf PostgreSQL 9.1 sind

%Vor%

Es ist ein bisschen länglich und Sie müssen die ID wiederholen, um mehrere Male zu testen, aber ich kann mir keine andere Lösung vorstellen, die eine einzelne SQL-Anweisung beinhaltet.

Wenn eine Zeile mit id=42 vorhanden ist, fügt der beschreibbare CTE nichts ein und die vorhandene Zeile wird daher vom zweiten Union-Teil zurückgegeben.

Beim Testen dachte ich eigentlich, dass die neue Zeile zweimal zurückgegeben würde (also ein union nicht ein union all ), aber es stellt sich heraus, dass das Ergebnis der zweiten SELECT-Anweisung tatsächlich ausgewertet wird, bevor die gesamte Anweisung ausgeführt wird Die neu eingefügte Zeile wird nicht angezeigt. Wenn also eine neue Zeile eingefügt wird, wird sie aus dem "zurückkehrenden" Teil übernommen.

    
a_horse_with_no_name 07.04.2012 21:31
quelle
0
%Vor%     
Clodoaldo Neto 07.04.2012 20:29
quelle

Tags und Links