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

SET CONSTRAINTS ALL DEFERRED funktioniert nicht wie erwartet

Nur DEFERRABLE Beschränkungen können verschoben werden.

Lassen Sie mich zuerst überlegene Alternativen vorschlagen:

1. INSERT um

Kehren Sie die Reihenfolge von INSERT um Aussagen und nichts muss verschoben werden. Am einfachsten und schnellsten - wenn überhaupt möglich.

2. Einzelbefehl

Erledigen Sie dies mit einem einzelnen Befehl . Dann muss immer noch nichts zurückgestellt werden, da nicht-aufschiebbare Constraints nach jedem Befehl geprüft werden und CTEs werden als Teil eines einzelnen Befehls betrachtet:

WITH ins1 AS (
   INSERT INTO b(j) VALUES(2)
   )
INSERT INTO a(i) VALUES(2);

Wenn Sie schon dabei sind, können Sie die Werte für das erste INSERT wiederverwenden; sicherer / bequemer für bestimmte Fälle oder mehrreihige Einsätze:

WITH ins1 AS (
   INSERT INTO b(j) VALUES(3)
   RETURNING j
   )
INSERT INTO a(i)
SELECT j FROM ins1;

Aber ich brauche verzögerte Beschränkungen! (Wirklich?)

ALTER TABLE b ADD CONSTRAINT fkey_ij FOREIGN KEY (j)
   REFERENCES a (i) MATCH SIMPLE
   ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE;  -- !!!

Dann funktioniert Ihr Originalcode (etwas langsamer, da verzögerte Einschränkungen Kosten verursachen).

db<>fiddle hier

Verwandte:

Meine ursprüngliche Antwort zitierte das Handbuch :

Aber das war irreführend, da es nur für "referenzielle Aktionen" gilt, dh was ON UPDATE passiert oder ON DELETE zu Zeilen in der referenzierten Tabelle. Der vorliegende Fall ist keiner von diesen - wie @zer0hedge darauf hingewiesen .