Ich habe eine Tabelle tag
mit 2 Spalten: id
(UUID) und name
(Text). Ich möchte jetzt ein neues Tag in die Tabelle einfügen, aber wenn das Tag bereits vorhanden ist, möchte ich einfach id
den vorhandenen Datensatz abrufen.
Ich nahm an, ich könnte nur ON CONFLICT DO NOTHING
in Kombination mit RETURNING "id"
:
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT DO NOTHING
RETURNING "id";
Dies gibt jedoch eine leere Ergebnismenge zurück, wenn das Tag mit dem Namen "foo" bereits vorhanden ist.
Ich habe dann die Abfrage geändert, um eine noop- DO UPDATE
Klausel zu verwenden:
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT ("name") DO UPDATE SET "name" = 'foo'
RETURNING "id";
Dies funktioniert wie beabsichtigt, ist jedoch etwas verwirrend, da ich nur den Namen auf den bereits vorhandenen Wert setze.
Ist dies der Weg, um dieses Problem zu lösen, oder gibt es einen einfacheren Ansatz, den ich vermisse?
postgresql
upsert
postgresql-9.5
Der Hochstapler
quelle
quelle
returning excluded.id
?ERROR: missing FROM-clause entry for table "excluded"
bei der VerwendungDO NOTHING
.Antworten:
Dies funktioniert (soweit ich es getestet habe) in allen 3 Fällen, wenn die einzufügenden Werte alle neu oder alle bereits in der Tabelle oder einer Mischung sind:
Es gibt wahrscheinlich einige andere Möglichkeiten, dies zu tun, möglicherweise ohne die neue
ON CONFLICT
Syntax zu verwenden.quelle
Keine Ahnung, wie sich das verhält, aber als weitere Möglichkeit, es zu versuchen, wird hier das Gleiche auf eine altmodische Art und Weise (ohne
ON CONFLICT
) getan :Das heißt, fügen Sie nur die [eindeutigen] Namen ein, die nicht in der
tag
Tabelle gefunden wurden, und geben Sie die IDs zurück. Kombinieren Sie dies mit den IDs der Namen, die in existierentag
, für die endgültige Ausgabe. Sie können auchname
, wie von ypercube® vorgeschlagen , in die Ausgabe werfen , damit Sie wissen, welche ID mit welchem Namen übereinstimmt.quelle
SELECT .. FROM ins UNION ALL SELECT ... FROM val JOIN tag ... ;