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

Ist es möglich, eine Fremdschlüsselverletzung in Postgres abzufangen

Wenn Sie jeweils nur eine einzelne Zeile einfügen, können Sie einen Speicherpunkt vor dem Einfügen und rollback hinzufügen, wenn das Einfügen fehlschlägt (oder freigeben wenn die Einfügung erfolgreich ist).

Für Postgres 9.5 oder höher können Sie INSERT ... ON CONFLICT DO NOTHING der tut, was er sagt. Sie können auch schreibe ON CONFLICT DO UPDATE SET column = value... , wodurch Ihre Einfügung automatisch in eine Aktualisierung der Zeile konvertiert wird, mit der Sie in Konflikt stehen (diese Funktionalität wird manchmal als "Upsert" bezeichnet).

Dies funktioniert nicht, da OP mit einem Fremdschlüssel arbeitet Einschränkung statt eindeutig Zwang. In diesem Fall können Sie am einfachsten die zuvor beschriebene savepoint-Methode verwenden, aber für mehrere Zeilen kann es sich als mühsam erweisen. Wenn Sie mehrere Zeilen auf einmal einfügen müssen, sollte es vernünftig sein, sie in mehrere Einfügeanweisungen aufzuteilen, vorhanden Sie arbeiten nicht im Autocommit-Modus , alle Einfügungen erfolgen in einer Transaktion, und Sie fügen nicht sehr viele Zeilen ein.

Manchmal brauchen Sie wirklich mehrere Einfügungen in einer einzigen Anweisung, weil der Roundtrip-Overhead für die Kommunikation mit Ihrer Datenbank plus die Kosten für Sicherungspunkte bei jeder Einfügung einfach zu hoch sind. In diesem Fall gibt es eine Reihe von unvollkommenen Ansätzen. Wahrscheinlich das am wenigsten schlechte besteht darin, eine verschachtelte Abfrage zu erstellen, die Ihre Daten auswählt und sie mit der anderen Tabelle verbindet, etwa so:

INSERT INTO table_A (column_A, column_B, column_C)
SELECT A_rows.*
FROM VALUES (...) AS A_rows(column_A, column_B, column_C)
JOIN table_B ON A_rows.column_B = table_B.column_B;