Comment une CASCADE de supprimer à partir d'une table d'enfant à la table parent?
J'ai préparé un violon qui illustre le problème.
CREATE TABLE parent (
parent_id integer primary key
);
CREATE TABLE child (
child_name TEXT primary key,
parent_id integer REFERENCES parent (parent_id) ON DELETE CASCADE
);
INSERT INTO parent VALUES (1);
INSERT INTO child VALUES ('michael',1), ('vanessa', 1);
Je veux un moyen pour que la suppression en CASCADE à l'enregistrement parent d'un enfant lorsque l'enregistrement est supprimé.
Par exemple:
DELETE FROM child WHERE child_name='michael';
Cela devrait cascade à la table parent et supprimer l'enregistrement.
OriginalL'auteur samol | 2014-03-18
Vous devez vous connecter pour publier un commentaire.
Les clés étrangères ne fonctionnent que dans l'autre sens: les suppressions en cascade de parent à enfant, de sorte que lorsque le parent (référencé) enregistrement est supprimé, tout enfant (référencement) les dossiers sont également supprimés.
Si c'est une relation 1:1 vous pouvez créer un bi-directionnelle relation de clé étrangère, où un côté est
DEFERRABLE INITIALLY DEFERRED
, et les deux côtés sont en cascade.Sinon, vous voulez un
ON DELETE ... FOR EACH ROW
trigger sur la table enfant qui supprime la ligne parent si il ne reste pas d'enfants. C'est potentiellement sujette à des conditions de course avec simultanéesINSERT
s; vous aurez besoin deSELECT ... FOR UPDATE
l'enregistrement parent, puis vérifier pour d'autres enregistrements enfants. Contrôle des clefs étrangères sur insérer prendre unFOR SHARE
de verrouillage sur le référencés (parent) afin d'éviter toute situation de concurrence.PostgreSQL est transactionnelle, et déclenche exécuter à l'intérieur de l'opération de l'instruction qui a tiré. Donc, si la DB se bloque, soit l'ensemble de la chose, ou rien de tout cela, sera engagée. Le scénario que vous décrivez ne peut pas se produire.
Vous pouvez également utiliser une déclaration de niveau de SUPPRIMER de DÉCLENCHEMENT: après les suppressions ont "commis" (entre parenthèses, parce que nous sommes toujours dans la même transaction de bloc) sur la table d'enfant de supprimer tous les parents avec 0 enfants. Cela permettrait d'éviter le potentiel condition de course.
Voulez-vous dire une contrainte différée déclencheur? Si donc, oui, cela fonctionne aussi longtemps que il n'y a pas d'autres différé des déclencheurs qui peuvent entrer en conflit.
J'étais en fait en se référant à la question de la suppression de plusieurs enfants. Plutôt que de vérifier sur chaque individu de supprimer, de faire la vérification de la mère après tous les suppressions ont eu lieu, d'où la déclaration de niveau de déclenchement. Je suppose que l'utilisation d'un différé de déclenchement peut également fonctionner. Mais en y regardant de plus lire, je ne vois pas la condition de la course vous de mentionner; la question était de savoir Supprime pas les Insertions. Pouvez-vous développer?
OriginalL'auteur Craig Ringer
Vous semblez vouloir tuer toute la famille, sans égard aux autres enfants. Exécuter ce lieu de
DELETE FROM child ...
:Alors tout fonctionne avec votre conception actuelle. Si vous insistez sur l'original de votre
DELETE
déclaration, vous besoin une règle ou d'un déclencheur. Mais ce serait plutôt compliqué.SUPPRIMER
énoncé dans le manuel.JOIN
dansSELECT
?C'est le mot-clé à se joindre à d'autres tables dans un
DELETE
déclaration. DepuisFROM
était déjà pris (DELETE FROM
) ... j'ai ajouté un lien vers le manuel de ma réponse.OriginalL'auteur Erwin Brandstetter
De votre question et sql violon, êtes-vous sûr que vous voulez supprimer de la mère ET tous les enfants si un enfant est supprimé? Si oui, alors utiliser ceci:
Il est impératif que vous
RETURN NULL
de laBEFORE DELETE
déclencheur: vous souhaitez supprimer à l'échec. La raison en est que vous supprimez le parent et que la suppression en cascade à la table d'enfant (avec les paramètres appropriés sur la table parent). Ensuite, si vous essayez de supprimer plus d'enfants dans la même instruction que vous essayez de faire fonctionner le système sur le manque de données et de jeter un parent qui est déjà allé.OriginalL'auteur Patrick