Warnung: Dies ist nicht sicher, wenn mehrere Sitzungen gleichzeitig ausgeführt werden (siehe Vorsichtsmaßnahmen unten).
Eine andere clevere Möglichkeit, ein "UPSERT" in postgresql zu erstellen, besteht darin, zwei aufeinanderfolgende UPDATE / INSERT-Anweisungen auszuführen, die jeweils so konzipiert sind, dass sie erfolgreich sind oder keine Auswirkungen haben.
UPDATE table SET field='C', field2='Z' WHERE id=3;
INSERT INTO table (id, field, field2)
SELECT 3, 'C', 'Z'
WHERE NOT EXISTS (SELECT 1 FROM table WHERE id=3);
Das UPDATE ist erfolgreich, wenn bereits eine Zeile mit "id = 3" vorhanden ist, andernfalls hat es keine Auswirkung.
Das INSERT ist nur erfolgreich, wenn die Zeile mit "id = 3" noch nicht vorhanden ist.
Sie können diese beiden zu einer einzigen Zeichenfolge kombinieren und beide mit einer einzigen SQL-Anweisung ausführen, die von Ihrer Anwendung ausgeführt wird. Es wird dringend empfohlen, sie zusammen in einer einzigen Transaktion auszuführen.
Dies funktioniert sehr gut, wenn es isoliert oder in einer gesperrten Tabelle ausgeführt wird, unterliegt jedoch Rennbedingungen, die bedeuten, dass es bei gleichzeitiger Einfügung einer Zeile immer noch mit einem doppelten Schlüsselfehler fehlschlägt oder beim gleichzeitigen Löschen einer Zeile ohne eingefügte Zeile endet . Eine SERIALIZABLE
Transaktion unter PostgreSQL 9.1 oder höher wird auf Kosten einer sehr hohen Serialisierungsfehlerrate zuverlässig abgewickelt, was bedeutet, dass Sie viel wiederholen müssen. Sehen Sie, warum Upsert so kompliziert ist , und diskutieren Sie diesen Fall ausführlicher.
Dieser Ansatz unterliegt auch isoliert verlorenen Aktualisierungen, es read committed
sei denn, die Anwendung überprüft die Anzahl der betroffenen Zeilen und überprüft, ob entweder die insert
oder die update
betroffene Zeile vorhanden ist .