Question

Dans MSSQL 2005, je viens de frapper le fameux message d'erreur:

  

L'introduction de la contrainte XXX FOREIGN KEY sur la table YYY peut provoquer des cycles ou plusieurs chemins en cascade. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION ou modifiez d'autres contraintes FOREIGN KEY.

Maintenant, StackOverflow ayant plusieurs sujets à propos de ce message d'erreur, j'ai déjà la solution (dans mon cas, je vais devoir utiliser des déclencheurs), mais je suis curieux de savoir pourquoi il y a un tel problème. .

Si je comprends bien, ils souhaitent éviter deux scénarios: un cycle et des chemins multiples. Un cycle serait où deux tables ont des clés étrangères en cascade les unes aux autres. OK, un cycle peut aussi couvrir plusieurs tables, mais ceci est le cas de base et sera plus facile à analyser.

Il existe plusieurs chemins lorsque TableA a des clés étrangères à TableB et TableC, et que TableB a également une clé étrangère à TableC. Encore une fois, c’est le cas de base minimum.

Je ne vois aucun problème pouvant survenir lorsqu'un enregistrement serait supprimé ou mis à jour dans l'une de ces tables. Bien sûr, vous devrez peut-être interroger la même table plusieurs fois pour voir quels enregistrements doivent être mis à jour / supprimés, mais s'agit-il vraiment d'un problème? Est-ce un problème de performance?

Dans d’autres sujets SO, les gens vont jusqu’à étiqueter en utilisant cascades comme suit: " risqué " et indiquez que " la résolution des chemins en cascade est un problème complexe " ;. Pourquoi? Où est le risque? Où est le problème?

Était-ce utile?

La solution

Vous avez une table enfant avec 2 chemins d'accès en cascade du même parent: un "effacer", un "null".

Qu'est-ce qui prime? Qu'attendez-vous après? etc

Remarque: un déclencheur est un code et peut ajouter des informations ou des conditions à une cascade.

Autres conseils

La raison pour laquelle nous interdisons l'utilisation de la suppression en cascade est liée aux performances et au verrouillage. Oui, ce n'est pas si grave lorsque vous supprimez un enregistrement, mais tôt ou tard, vous devrez supprimer un grand groupe d'enregistrements et votre base de données s'immobilisera.

Si vous supprimez suffisamment d'enregistrements, SQL Server peut devenir un verrou de table et personne ne peut rien faire avec la table jusqu'à ce qu'il soit terminé.

Nous avons récemment transféré l'un de nos clients sur son propre serveur. Dans le cadre de la transaction, nous avons également dû supprimer tous les enregistrements de ce client de notre serveur d'origine. La suppression de toutes ses informations par lots (afin de ne pas causer de problèmes avec d'autres utilisateurs) a pris quelques mois. Si nous avions configuré la suppression en cascade, la base de données aurait été inaccessible pendant longtemps aux autres clients, car des millions d'enregistrements ont été supprimés dans une transaction et des centaines de tables ont été verrouillées jusqu'à la fin de la transaction.

Je pourrais également voir un scénario dans lequel une impasse aurait pu se produire lors de l’utilisation de la suppression en cascade, car nous n’avions aucun contrôle sur l’ordre que le chemin de la cascade aurait suivi et notre base de données est quelque peu dénormalisée avec clientid figurant dans la plupart des tables. Donc, si elle verrouille la table contenant une clé étrangère également sur une troisième table, ainsi que la table client se trouvant dans un chemin différent, elle ne pourra peut-être pas vérifier cette table afin de la supprimer de la troisième table car c'est tout une transaction et les verrous ne seraient pas libérés tant que ce ne serait pas fait. Donc, il n’aurait peut-être pas été possible de configurer des suppressions en cascade s’il voyait la possibilité de créer des blocages dans la transaction.

Une autre raison d'éviter les suppressions en cascade est que l'existence d'un enregistrement enfant est parfois une raison suffisante pour ne pas supprimer l'enregistrement parent. Par exemple, si vous avez une table client et que ce client a déjà passé des commandes, vous ne voudriez pas le supprimer et perdre les informations sur la commande réelle.

Considérons un tableau d'employés:

CREATE TABLE Employee
(
    EmpID   INTEGER NOT NULL PRIMARY KEY,
    Name    VARCHAR(40) NOT NULL,
    MgrID   INTEGER NOT NULL REFERENCES Employee(EmpID) ON DELETE CASCADE
);

INSERT INTO Employees(     1, "Bill",   1);
INSERT INTO Employees(    23, "Steve",  1);
INSERT INTO Employees(234212, "Helen", 23);

Supposons maintenant que Bill se retire:

DELETE FROM Employees WHERE Name = "Bill";

Ooooppps; tout le monde vient d'être limogé!

[ Nous pouvons discuter si les détails de la syntaxe sont corrects; le concept est valable, je pense. ]

Je pense que le problème est que, lorsque vous créez un chemin "ON DELETE CASCADE", et l’autre "ON DELETE RESTRICT", ou "NO ACTION". le résultat (le résultat) est imprévisible. Cela dépend du déclencheur de suppression (il s’agit également d’un déclencheur, mais vous n’avez pas à le créer vous-même) sera exécuté en premier.

Je suis d'accord avec le fait que les cascades soient "risquées". et devrait être évité. (Je préfère personnellement mettre en cascade les modifications manuellement plutôt que d’avoir le serveur SQL en charge automatiquement). C’est aussi parce que même si le serveur SQL supprimait des millions de lignes, le résultat serait toujours affiché comme

(1 ligne (s) affectée (s))

Je pense que l’utilisation d’une option ON DELETE CASCADE est une question de modèle commercial que vous implémentez. Une relation entre deux objets métier peut être soit une simple "association", où les deux extrémités de la relation sont liées, mais sinon des objets indépendants dont le cycle de vie est différent et contrôlé par une autre logique. Cependant, il existe également des "agrégations". relations, où un objet peut en réalité être vu comme le "parent" ou " propriétaire " d'un " enfant " ou " detail " objet. Il y a la notion encore plus forte de "composition" relation, où un objet existe uniquement en tant que composition de plusieurs parties. Dans le "" association" Dans ce cas, vous ne déclarerez généralement pas de contrainte ON DELETE CASCADE. Cependant, pour les agrégations ou les compositions, ON DELETE CASCADE vous aide à mapper votre modèle économique à la base de données avec plus de précision et de manière déclarative. C'est pourquoi le fait que MS SQL Server limite l'utilisation de cette option à un seul chemin en cascade me dérange. Si je ne me trompe pas, de nombreux autres systèmes de base de données SQL largement utilisés n'imposent pas de telles restrictions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top