PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

SET CONSTRAINTS ALL DEFERRED ne fonctionne pas comme prévu

Uniquement DEFERRABLE les contraintes peuvent être différées.

Permettez-moi de suggérer d'abord des alternatives supérieures :

1. INSERT dans l'ordre

Inverser la séquence du INSERT déclarations et rien ne doit être différé. Le plus simple et le plus rapide - si possible.

2. Commande unique

Faites-le en une commande unique . Ensuite, rien n'a encore besoin d'être reporté, car les contraintes non reportables sont vérifiées après chaque commande et les CTE sont considérés comme faisant partie d'un commandement unique :

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

Pendant que vous y êtes, vous pouvez réutiliser les valeurs pour le premier INSERT; plus sûr / plus pratique pour certains cas ou inserts multi-rangs :

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

Mais j'ai besoin de contraintes différées ! (Vraiment ?)

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

Ensuite, votre code d'origine fonctionne (un peu plus lentement, car les contraintes différées augmentent les coûts).

db<>violon ici

Connexe :

Ma réponse d'origine citait le manuel :

Mais c'était trompeur car cela ne s'applique qu'aux "actions référentielles", c'est-à-dire ce qui se passe ON UPDATE ou ON DELETE aux lignes de la table référencée. Le cas en question n'en fait pas partie - car @zer0hedge souligné .