PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

IMPOSTA VINCOLI TUTTI DIFFERITI non funziona come previsto

Solo DEFERRABLE i vincoli possono essere differiti.

Lasciatemi suggerire prima alternative superiori:

1. INSERT in ordine

Invertire la sequenza di INSERT dichiarazioni e nulla deve essere differito. Il più semplice e veloce, se possibile.

2. Comando singolo

Fallo con un comando singolo . Quindi ancora nulla deve essere differito, poiché i vincoli non differibili vengono controllati dopo ogni comando e i CTE sono considerati parte di un unico comando:

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

Mentre ci sei, puoi riutilizzare i valori per il primo INSERT; più sicuro/più conveniente per alcuni casi o inserti a più file:

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

Ma ho bisogno di vincoli posticipati! (Davvero?)

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

Quindi il tuo codice originale funziona (un po' più lento, poiché i vincoli posticipati aggiungono costi).

db<>violino qui

Correlati:

La mia risposta originale citava il manuale :

Ma era fuorviante in quanto si applica solo alle "azioni referenziali", ovvero cosa succede ON UPDATE o ON DELETE alle righe della tabella di riferimento. Il caso in questione non è uno di quelli, come @zer0hedge ha sottolineato .