2008-12-09 5 views
2

Je travaille sur une base de données qui suit les fichiers et les dépendances dans les projets. Brièvement, j'ai deux tables principales; la table PROJECTS répertorie les noms de projets et d'autres propriétés, la table FILES répertorie les fichiers. Chaque entrée de fichier pointe vers un projet en tant que clé étrangère définie sur CASCADE. Par conséquent, si je supprime un enregistrement de projet de la base de données, tous les enregistrements de fichier disparaissent également. Jusqu'ici tout va bien.Conflit CASCADE et RESTRICT exigences de clé étrangère?

Maintenant, j'ai une table supplémentaire DEPENDENCIES. Chaque enregistrement de la table de dépendances contient deux fichiers, spécifiant que le premier fichier dépend de la seconde. Encore une fois ce sont des clés étrangères, la première est CASCADE (donc si je supprime une entrée de fichier, cet enregistrement est supprimé), mais la seconde est définie sur RESTRICT (donc je ne suis pas autorisé à supprimer une entrée si d'autres fichiers dépendent dessus). Encore une fois, tout semble bien.

Malheureusement, il semble que je ne puisse plus supprimer un projet avec une seule instruction de suppression SQL! La suppression tente de supprimer en cascade les fichiers, mais si l'un d'entre eux apparaît dans la table DEPENDENCIES, la clé étrangère RESTRICT empêche la suppression (même si cet enregistrement dans la table des dépendances sera supprimé car l'autre colonne est CASCADE). La seule solution de contournement que j'ai consiste à calculer un ordre exact pour supprimer les fichiers afin qu'aucune des contraintes d'enregistrement de dépendance ne soit violée, et supprimer les enregistrements de fichier un à la fois avant d'essayer de supprimer le projet.

Est-il possible de configurer mon schéma de base de données afin qu'une seule suppression SQL de la table des projets cascade correctement les autres suppressions? J'utilise Firebird 2.1, mais je ne sais pas si cela fait une différence - il semble qu'il devrait y avoir un moyen de faire ce travail?

Répondre

4

Vous ne pouvez pas contrôler l'ordre de suppression par une cascade de clé étrangère, mais vous pourriez être en mesure de concevoir un déclencheur sur PROJECTS pour supprimer des lignes de FILES qui appartiennent à ce projet et sont également répertoriés dans DEPENDENCIES comme dépendant d'autres FILES. Faites-en un déclencheur BEFORE DELETE, il devrait donc être exécuté avant les effets en cascade.

Quelque chose comme ceci:

CREATE TRIGGER Del_Child_Files FOR PROJECTS 
BEFORE INSERT 
AS BEGIN 
    FOR SELECT F.FILE_ID FROM FILES F JOIN DEPENDENCIES D 
     ON F.FILE_ID = D.CHILD_ID 
    WHERE F.PROJECT_ID = OLD.PROJECT_ID 
    INTO :file_id 
    DO 
    DELETE FROM FILES WHERE FILE_ID = :file_id; 
    DONE 
END 

Ainsi, lorsque vous supprimez un projet, cela supprime tous les fichiers « enfant » d'un projet qui dépendent d'autres fichiers, et cette cascade pour supprimer des lignes en DEPENDENCIES de sorte que tous les fichiers restants sont exempts de dépendances. Votre suppression du projet peut maintenant cascade pour supprimer ces fichiers.

Je n'ai pas testé cela et ma syntaxe Firebird peut être rouillée, mais peut-être que cela vous aidera à démarrer.

Évidemment, s'il vous plaît tester ceci sur une copie de vos données, pas les données en direct!

+0

J'aime vraiment l'idée de le faire dans un déclencheur plutôt que dans le code de l'application. Je vais essayer et ressemble à ceci sera la réponse pour moi :) – Chris

0

Le système prend-il en charge les contraintes différées, dans lesquelles la vérification des contraintes peut être différée jusqu'à un point de validation?

Peut-être que c'est juste une chose Oracle.

+0

Firebird ne prend pas en charge les contraintes différées. –

Questions connexes