Question

Lors de la configuration de clés étrangères dans SQL Server, dans quelles circonstances devez-vous les faire en cascade lors de la suppression ou de la mise à jour, et quelle est la raison derrière cela ?

Cela s'applique probablement également à d'autres bases de données.

Je recherche avant tout des exemples concrets de chaque scénario, de préférence venant de quelqu'un qui les a utilisés avec succès.

Était-ce utile?

La solution

Résumé de ce que j'ai vu jusqu'à présent :

  • Certaines personnes n’aiment pas du tout les cascades.

Supprimer en cascade

  • La suppression en cascade peut avoir du sens lorsque la sémantique de la relation peut impliquer une "fait partie de" description.Par exemple, un enregistrement OrderLine fait partie de sa commande parent et les OrderLines ne seront jamais partagées entre plusieurs commandes.Si la commande devait disparaître, la ligne de commande devrait également disparaître, et une ligne sans commande poserait un problème.
  • L'exemple canonique pour Cascade Delete est SomeObject et SomeObjectItems, où cela n'a aucun sens qu'un enregistrement d'éléments existe sans un enregistrement principal correspondant.
  • Tu devrais pas utilisez Cascade Supprimer si vous préservez l'historique ou utilisez une "suppression logicielle/logique" dans laquelle vous définissez uniquement une colonne de bits supprimée sur 1/vrai.

Mise à jour en cascade

  • La mise à jour en cascade peut avoir du sens lorsque vous utilisez une clé réelle plutôt qu'une clé de substitution (colonne d'identité/auto-incrémentation) dans les tables.
  • L'exemple canonique de Cascade Update est celui où vous disposez d'une clé étrangère mutable, comme un nom d'utilisateur qui peut être modifié.
  • Tu devrais pas utilisez Cascade Update avec des clés qui sont des colonnes d'identité/auto-incrémentation.
  • Il est préférable d'utiliser Cascade Update en conjonction avec une contrainte unique.

Quand utiliser la cascade

  • Vous souhaiterez peut-être obtenir une confirmation très forte de la part de l'utilisateur avant d'autoriser une opération en cascade, mais cela dépend de votre application.
  • La cascade peut vous causer des ennuis si vous configurez mal vos clés étrangères.Mais ça devrait aller si vous faites ça correctement.
  • Il n'est pas judicieux d'utiliser la cascade avant de bien la comprendre.Cependant, il s’agit d’une fonctionnalité utile et mérite donc de prendre le temps de la comprendre.

Autres conseils

Les clés étrangères constituent le meilleur moyen de garantir l’intégrité référentielle d’une base de données.Éviter les cascades parce qu'elles sont magiques, c'est comme tout écrire en assembleur parce que vous ne faites pas confiance à la magie derrière les compilateurs.

Ce qui est mauvais, c'est la mauvaise utilisation des clés étrangères, comme par exemple les créer à l'envers.

L'exemple de Juan Manuel est l'exemple canonique, si vous utilisez du code, il y a beaucoup plus de chances de laisser des DocumentItems parasites 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, par exemple, une clé primaire d'une table d'utilisateurs est la combinaison nom-nom.Ensuite, vous souhaitez que les modifications apportées à cette combinaison se propagent partout où elles sont référencées.

@Aidan, Cette clarté à laquelle vous faites référence a un coût élevé, le risque de laisser des données fausses dans votre base de données, ce qui est pas petit.Pour moi, c'est généralement simplement le manque de familiarité avec la DB et l'incapacité de trouver quels FK sont en place avant de travailler avec la DB qui entretiennent cette peur.Soit cela, soit une utilisation abusive constante de la cascade, en l'utilisant là où les entités n'étaient pas conceptuellement liées, ou là où vous devez préserver l'histoire.

Je n'utilise jamais de suppressions en cascade.

Si je veux que quelque chose soit supprimé de la base de données, je veux indiquer explicitement à la base de données ce que je veux supprimer.

Bien sûr, il s'agit d'une fonction disponible dans la base de données et il peut y avoir des moments où vous pouvez les utiliser, par exemple si vous avez une table « order » et une table « orderItem », vous souhaiterez peut-être effacer les éléments lorsque vous supprimez un commande.

J'aime la clarté que j'obtiens en le faisant dans le code (ou dans une procédure stockée) plutôt que par « 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 ».

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 modifie simplement les contraintes dans le diagramme dans Management Studio et je n'ai pas besoin de modifier sp ou dataaccess.

Cela dit, j'ai un problème avec les suppressions en cascade et ce sont des références circulaires.Cela conduit souvent à des parties de la base de données qui ne subissent aucune suppression en cascade.

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 reporting 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 été modifiés depuis la dernière importation, puis je réimporte les enregistrements modifiés et tout ce qui s'y rapporte.Cela m'évite d'avoir à écrire de nombreuses suppressions compliquées qui vont du bas vers le haut de ma base de données.

Je ne considère pas les suppressions en cascade comme aussi mauvaises que les déclencheurs car elles suppriment uniquement 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.-à-d.ayant une colonne de bits appelée isDeleted qui est définie sur true) à la place.

Un exemple est lorsque vous avez des dépendances entre entités...c'est à dire:Document -> DocumentItems (lorsque vous supprimez Document, DocumentItems n'a aucune raison d'exister)

Utilisez la suppression en cascade lorsque 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, où le dossier n’a aucun sens sans le dossier 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.

ON Supprimer la cascade :

Quand tu veux lignes de la table enfant à supprimer Si la ligne correspondante est supprimée dans la table parent.

Si lors de la suppression en cascade n'est pas utilisé, une erreur sera générée pour intégrité référentielle.

ON Mise à jour en cascade :

Quand tu veux changement de clé primaire à mettre à jour dans clé étrangère

L’une des raisons d’effectuer une suppression en cascade (plutôt que de la faire dans le code) est d’améliorer les performances.

Cas 1:Avec une suppression en cascade

 DELETE FROM table WHERE SomeDate < 7 years ago;

Cas 2 :Sans suppression en cascade

 FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

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".Sinon, un idiot supprimera la moitié de votre base de données lorsque vous le ferez :

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'

J'ai entendu parler de DBA et/ou de « Politique d'entreprise » qui interdisent l'utilisation de « On Supprimer Cascade » (et autres) uniquement en raison de mauvaises expériences passées.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, des déclencheurs sont parfois nécessaires au lieu de "en cascade lors de la suppression", 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 Supprimer.Un avantage clé de la cascade "On Supprimer" est qu'elle 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 du développement et de ce que disent les spécifications.Une interdiction de tapis basée sur une mauvaise expérience ne devrait pas être le critère ;le processus de réflexion « Ne jamais utiliser » est au mieux draconien.Il faut faire preuve de jugement à chaque fois et apporter des modifications à mesure que le modèle économique évolue.

N'est-ce pas cela le développement ?

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 grâce à l'utilisation de déclencheurs.Ils ont tendance à vous mordre le cul à un moment donné, soit lorsqu'ils tentent de détecter un bug, soit lorsqu'ils diagnostiquent des problèmes de performances.

Là où je les utiliserais, c'est pour garantir la cohérence sans trop d'effort.Pour obtenir le même effet, vous devrez utiliser des procédures stockées.

Comme tout le monde ici, je trouve que les suppressions en cascade ne sont vraiment que marginalement utiles (ce n'est vraiment pas beaucoup de travail pour 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 lorsque quelqu'un supprime accidentellement en cascade certaines données importantes difficiles à restaurer.

Le seul cas où j'utiliserais est si les données de la table sont hautement contrôlées (par exemple, 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é.

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 :

  1. Rejet
  2. Propagation
  3. annulation.

La propagation est appelée cascade.

Il y a deux cas :

‣ Si un tuple dans S a été supprimé, supprimez les tuples R 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.

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 du détenteur du PK ou appartiennent à celui-ci.Sinon, tous les modules nécessiteraient des correctifs immédiats pour nettoyer leurs éléments dépendants avant de supprimer le propriétaire du 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éconseillée depuis un certain temps.Ce n'est pas trop grave non plus si des 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 du tableau "couleurs", et tous les éléments jaunes de la base de données sont supprimés.En outre, ceux-ci sont parfois mis à jour de manière supprimer tout insérer tout, ce qui conduit à une intégrité référentielle totalement omise.Bien sûr, c'est faux, mais comment changer un logiciel complexe qui fonctionne depuis de nombreuses années, avec l'introduction d'une véritable intégrité référentielle risquant d'avoir 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 encore une fois des déclencheurs ou un code spécifique pour conserver la valeur de clé redondante (sauf après la suppression du PK).

Les suppressions en cascade sont extrêmement utiles lors de l’implémentation d’entités logiques de super-type et de sous-type dans une base de données physique.

Lorsque des tables de super-types et de sous-types distinctes sont utilisées pour implémenter physiquement des super-types/sous-types (par opposition au regroupement de tous les attributs de sous-types dans une seule table de super-types physique), il existe un -une relation entre ces tables et le problème devient alors de savoir comment garder les clés primaires synchronisées à 100 % 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 supprime l'enregistrement de super-type correspondant, qui, à son tour, supprime en cascade l'enregistrement de sous-type.

L'utilisation des suppressions en cascade de cette manière garantit qu'aucun enregistrement de super-type ou de sous-type orphelin n'existe, que vous supprimiez d'abord l'enregistrement de super-type ou l'enregistrement de sous-type.

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