Lors de la configuration de clés étrangères dans SQL Server, dans quelles circonstances devez-vous les mettre en cascade lors de la suppression ou de la mise à jour, et quel en est le raisonnement?
Cela s'applique probablement aussi à d'autres bases de données.
Je recherche surtout des exemples concrets de chaque scénario, de préférence de quelqu'un qui les a utilisés avec succès.
sql-server
database-design
foreign-keys
rdbms
cascade
Joël Coehoorn
la source
la source
sql-server
balise.Réponses:
Résumé de ce que j'ai vu jusqu'à présent:
Suppression en cascade
Mise à jour en cascade
Quand utiliser la cascade
la source
Les clés étrangères sont le meilleur moyen de garantir l'intégrité référentielle d'une base de données. Éviter les cascades parce que c'est magique, c'est comme tout écrire en assemblage parce que vous ne faites pas confiance à la magie des compilateurs.
Ce qui est mauvais, c'est la mauvaise utilisation des clés étrangères, comme les créer à l'envers, par exemple.
L'exemple de Juan Manuel est l'exemple canonique, si vous utilisez du code, il y a beaucoup plus de chances de laisser de faux DocumentItems dans la base de données qui viendront vous mordre.
Les mises à jour en cascade sont utiles, par exemple, lorsque vous avez des références aux données par quelque chose qui peut changer, disons qu'une clé primaire d'une table users est le nom, la combinaison de nom. Ensuite, vous voulez que les modifications de cette combinaison se propagent là où elles sont référencées.
@Aidan, Cette clarté dont vous parlez a un coût élevé, le risque de laisser des données fausses dans votre base de données, ce qui n'est pas petit . Pour moi, c'est généralement juste un manque de familiarité avec la DB et l'incapacité de trouver quels FK sont en place avant de travailler avec la DB qui alimentent cette peur. Soit cela, soit une utilisation abusive constante de la cascade, en l'utilisant là où les entités n'étaient pas liées conceptuellement, ou là où vous devez préserver l'histoire.
la source
Je n'utilise jamais de suppressions en cascade.
Si je veux que quelque chose soit supprimé de la base de données, je veux dire explicitement à la base de données ce que je veux retirer.
Bien sûr, il s'agit d'une fonction disponible dans la base de données et il peut y avoir des moments où il est acceptable de les utiliser, par exemple si vous avez une table 'order' et une table 'orderItem', vous voudrez peut-être effacer les éléments lorsque vous supprimez un ordre.
J'aime la clarté que j'obtiens en le faisant dans le code (ou la procédure stockée) plutôt que dans la «magie».
Pour la même raison, je ne suis pas non plus fan des déclencheurs.
Quelque chose à noter est que si vous supprimez une 'commande', vous obtiendrez un rapport '1 ligne affectée' même si la suppression en cascade a supprimé 50 'orderItem'.
la source
Je travaille beaucoup avec des suppressions en cascade.
Il est bon de savoir que quiconque travaille sur la base de données ne laissera jamais de données indésirables. Si les dépendances augmentent, je change simplement les contraintes dans le diagramme dans Management Studio et je n'ai pas à modifier sp ou dataacces.
Cela dit, j'ai 1 problème avec les suppressions en cascade et les références circulaires. Cela conduit souvent à des parties de la base de données qui n'ont pas de suppressions en cascade.
la source
Je fais beaucoup de travail sur les bases de données et je trouve rarement les suppressions en cascade utiles. La seule fois où je les ai utilisés efficacement, c'est dans une base de données de rapports qui est mise à jour par un travail de nuit. Je m'assure que toutes les données modifiées sont importées correctement en supprimant tous les enregistrements de niveau supérieur qui ont changé depuis la dernière importation, puis réimportez les enregistrements modifiés et tout ce qui s'y rapporte. Cela m'évite d'avoir à écrire beaucoup de suppressions compliquées qui vont du bas vers le haut de ma base de données.
Je ne considère pas que les suppressions en cascade soient aussi mauvaises que les déclencheurs car elles ne suppriment que des données, les déclencheurs peuvent contenir toutes sortes de choses désagréables.
En général, j'évite complètement les suppressions réelles et j'utilise des suppressions logiques (c'est-à-dire avoir une colonne de bits appelée isDeleted qui est mise à true) à la place.
la source
Un exemple est lorsque vous avez des dépendances entre des entités ... c'est-à-dire: Document -> DocumentItems (lorsque vous supprimez Document, DocumentItems n'a pas de raison d'exister)
la source
Utilisez la suppression en cascade là où vous souhaitez que l'enregistrement avec le FK soit supprimé si son enregistrement PK de référence a été supprimé. En d'autres termes, lorsque l'enregistrement n'a pas de sens sans l'enregistrement de référence.
Je trouve la suppression en cascade utile pour garantir que les références mortes sont supprimées par défaut plutôt que de provoquer des exceptions nulles.
la source
ON Supprimer la cascade:
Lorsque vous souhaitez que les lignes de la table enfant soient supprimées Si la ligne correspondante est supprimée de la table parent.
Si la suppression en cascade n'est pas utilisée, une erreur sera générée pour l' intégrité référentielle .
ON Update Cascade:
Lorsque vous souhaitez que la modification de la clé primaire soit mise à jour dans la clé étrangère
la source
J'ai entendu parler des administrateurs de base de données et / ou de la «politique de l'entreprise» qui interdisent d'utiliser «On Delete Cascade» (et d'autres) uniquement en raison de mauvaises expériences dans le passé. Dans un cas, un gars a écrit trois déclencheurs qui ont fini par s'appeler. Trois jours pour récupérer ont abouti à une interdiction totale des déclencheurs, tout cela à cause des actions d'un idjit.
Bien sûr, parfois, des déclencheurs sont nécessaires au lieu de "En cas de suppression en cascade", comme lorsque certaines données enfants doivent être préservées. Mais dans d'autres cas, il est parfaitement valable d'utiliser la méthode en cascade On Delete. Un avantage clé de "On Delete cascade" est qu'il capture TOUS les enfants; une procédure de déclenchement / stockage écrite personnalisée peut ne pas l'être si elle n'est pas codée correctement.
Je pense que le développeur devrait être autorisé à prendre la décision en fonction de ce qu'est le développement et de ce que dit la spécification. Une interdiction de tapis basée sur une mauvaise expérience ne devrait pas être le critère; le processus de pensée «Ne jamais utiliser» est au mieux draconien. Un appel au jugement doit être fait à chaque fois, et des changements sont apportés à mesure que le modèle commercial évolue.
N'est-ce pas là tout le sens du développement?
la source
Une des raisons de mettre une suppression en cascade (plutôt que de le faire dans le code) est d'améliorer les performances.
Cas 1: avec une suppression en cascade
Cas 2: sans suppression en cascade
Deuxièmement, lorsque vous ajoutez une table enfant supplémentaire avec une suppression en cascade, le code du cas 1 continue de fonctionner.
Je mettrais seulement dans une cascade où la sémantique de la relation fait "partie de". Sinon, un idiot supprimera la moitié de votre base de données lorsque vous faites:
la source
J'essaie d'éviter les suppressions ou les mises à jour que je n'ai pas explicitement demandées dans le serveur SQL.
Soit en cascade, soit en utilisant des déclencheurs. Ils ont tendance à vous mordre dans le cul un certain temps, que ce soit lorsqu'ils essaient de localiser un bug ou lorsqu'ils diagnostiquent des problèmes de performance.
Là où je les utiliserais, c'est pour garantir la cohérence pour peu d'efforts. Pour obtenir le même effet, vous devrez utiliser des procédures stockées.
la source
Comme tout le monde ici, je trouve que les suppressions en cascade ne sont vraiment utiles que marginalement (ce n'est vraiment pas beaucoup de travail de supprimer des données référencées dans d'autres tables - s'il y a beaucoup de tables, vous automatisez simplement cela avec un script) mais vraiment ennuyeux lorsqu'une personne en cascade supprime accidentellement des données importantes difficiles à restaurer.
Le seul cas où j'utiliserais est si les données de la table de table sont hautement contrôlées (par exemple, des autorisations limitées) et uniquement mises à jour ou supprimées via un processus contrôlé (comme une mise à jour logicielle) qui a été vérifiée.
la source
Une suppression ou une mise à jour de S qui supprime une valeur de clé étrangère trouvée dans certains tuples de R peut être gérée de trois manières:
La propagation est appelée cascade.
Il y a deux cas:
‣ Si un tuple de S a été supprimé, supprimez les R tuples qui y faisaient référence.
‣ Si un tuple dans S a été mis à jour, mettez à jour la valeur dans les tuples R qui y font référence.
la source
Si vous travaillez sur un système avec de nombreux modules différents dans différentes versions, cela peut être très utile si les éléments supprimés en cascade font partie de / appartiennent au détenteur de PK. Sinon, tous les modules nécessiteraient des correctifs immédiats pour nettoyer leurs éléments dépendants avant de supprimer le propriétaire PK, ou la relation de clé étrangère serait complètement omise, laissant éventuellement des tonnes de déchets dans le système si le nettoyage n'est pas effectué correctement.
Je viens d'introduire la suppression en cascade pour une nouvelle table d'intersection entre deux tables déjà existantes (l'intersection à supprimer uniquement), après que la suppression en cascade ait été découragée depuis un certain temps. Ce n'est pas trop mal non plus si les données sont perdues.
C'est, cependant, une mauvaise chose sur les tables de liste de type énumération: quelqu'un supprime l'entrée 13 - jaune de la table "couleurs", et tous les éléments jaunes de la base de données sont supprimés. En outre, ceux-ci sont parfois mis à jour d'une manière delete-all-insert-all, conduisant à une intégrité référentielle totalement omise. Bien sûr, c'est faux, mais comment allez-vous changer un logiciel complexe qui fonctionne depuis de nombreuses années, l'introduction d'une véritable intégrité référentielle risquant de provoquer des effets secondaires inattendus?
Un autre problème est lorsque les valeurs de clé étrangère d'origine doivent être conservées même après la suppression de la clé primaire. On peut créer une colonne tombstone et une option ON DELETE SET NULL pour le FK d'origine, mais cela nécessite à nouveau des déclencheurs ou un code spécifique pour maintenir la valeur de clé redondante (sauf après la suppression de PK).
la source
Les suppressions en cascade sont extrêmement utiles lors de l'implémentation d'entités de super-types et de sous-types logiques dans une base de données physique.
Lorsque des tables de super-types et de sous-types séparées sont utilisées pour implémenter physiquement des super-types / sous-types (par opposition à regrouper tous les attributs de sous-type dans une seule table de super-type physique), il existe un -une relation entre ces tables et le problème devient alors comment garder les clés primaires 100% synchronisées entre ces tables.
Les suppressions en cascade peuvent être un outil très utile pour:
1) Assurez-vous que la suppression d'un enregistrement de super-type supprime également l'enregistrement de sous-type unique correspondant.
2) Assurez-vous que toute suppression d'un enregistrement de sous-type supprime également l'enregistrement de super-type. Ceci est réalisé en implémentant un déclencheur de suppression "au lieu de" sur la table de sous-type qui va et supprime l'enregistrement de super-type correspondant, qui, à son tour, supprime en cascade l'enregistrement de sous-type.
L'utilisation de suppressions en cascade de cette manière garantit qu'aucun enregistrement de super-type ou de sous-type orphelin n'existe jamais, que vous supprimiez d'abord l'enregistrement de super-type ou l'enregistrement de sous-type en premier.
la source