web-dev-qa-db-fra.com

Quel est le problème avec les clés étrangères?

Je me souviens avoir entendu Joel Spolsky mentionner dans podcast 014 qu'il avait à peine utilisé une clé étrangère (si je me souviens bien). Cependant, ils me paraissent assez essentiels pour éviter les doublons et les problèmes d’intégrité des données dans votre base de données.

Les gens ont-ils des raisons solides pour lesquelles (pour éviter une discussion dans le sens des principes du débordement de pile)?

Edit: "Je n'ai pas encore de raison de créer une clé étrangère, donc cela pourrait être ma première raison pour en créer un. "

247
ljs

Raisons d'utiliser des clés étrangères:

  • vous n'obtiendrez pas de rangs orphelins
  • vous pouvez obtenir le comportement Nice "on delete cascade" en nettoyant automatiquement les tables
  • connaître les relations entre les tables de la base de données aide l’Optimizer à planifier vos requêtes pour une exécution plus efficace, car il est en mesure d’obtenir de meilleures estimations de la cardinalité de la jointure.
  • Les FK donnent une idée assez précise des statistiques les plus importantes à collecter dans la base de données, ce qui conduit à de meilleures performances.
  • ils permettent toutes sortes de supports générés automatiquement - les ORM peuvent se générer eux-mêmes, les outils de visualisation pourront créer des schémas de schéma Nice pour vous, etc.
  • une personne nouvelle dans le projet se mettra plus rapidement au courant des choses, sinon les relations implicites sont explicitement documentées

Raisons pour ne pas utiliser de clés étrangères:

  • vous rendez la base de données supplémentaire à chaque opération CRUD car elle doit vérifier la cohérence FK. Cela peut être très coûteux si vous avez beaucoup de désabonnement
  • en imposant des relations, les FK spécifient un ordre dans lequel vous devez ajouter/supprimer des éléments, ce qui peut entraîner un refus de la base de données de faire ce que vous voulez. (D'accord, dans de tels cas, ce que vous essayez de faire est de créer une ligne orpheline, et ce n'est généralement pas une bonne chose). Cela est particulièrement pénible lorsque vous effectuez des mises à jour par lot volumineuses et que vous chargez une table avant une autre, la seconde table créant un état cohérent (mais si vous agissez de la sorte si le second chargement échoue et que votre la base de données est maintenant incohérente?).
  • parfois, vous savez à l'avance que vos données vont être sales, vous l'acceptez et vous voulez que la base de données l'accepte.
  • vous êtes juste paresseux :-)

Je pense (je ne suis pas certain!) Que la plupart des bases de données établies fournissent un moyen de spécifier une clé étrangère qui n'est pas appliquée, et qui constitue simplement un peu de métadonnées. Comme la non-application supprime toutes les raisons de ne pas utiliser les FK, vous devriez probablement suivre cette voie si l'une des raisons de la deuxième section s'applique.

344
SquareCog

C'est une question d'éducation. Si quelque part dans votre carrière scolaire ou professionnelle vous avez passé du temps à nourrir et à entretenir des bases de données (ou si vous avez travaillé en étroite collaboration avec des personnes talentueuses), alors les principes fondamentaux des entités et des relations sont bien enracinés dans votre processus de réflexion. Parmi ces rudiments, il y a comment, quand et pourquoi spécifier des clés dans votre base de données (primaires, étrangères et peut-être alternatives). C'est une seconde nature.

Si, toutefois, vous n'avez pas eu une expérience aussi approfondie ou positive de votre passé avec des projets liés au SGBDR, vous n'avez probablement pas été exposé à de telles informations. Ou peut-être que votre passé inclut une immersion dans un environnement qui était fortement anti-base de données (par exemple, "ces administrateurs de base de données sont des idiots - nous sommes peu nombreux, nous avons choisi peu de frondeurs de code Java/c # qui vont sauver la situation"), auquel cas vous pourriez être farouchement opposé aux babillards arcaniques de certains dweeb vous disant que les FK (et les contraintes qu’ils peuvent impliquer) sont vraiment importantes si vous voulez simplement écouter.

La plupart des gens ont appris à leur enfance qu’il était important de se brosser les dents. Pouvez-vous vous en passer? Bien sûr, mais à un moment donné, vous aurez moins de dents que si vous vous étiez brossé après chaque repas. Si les mères et les pères étaient suffisamment responsables pour couvrir la conception de la base de données ainsi que l'hygiène buccale, nous n'aurions pas cette conversation. :-)

79
Ed Lucas

Je suis sûr qu'il existe de nombreuses applications pour lesquelles vous pouvez vous en tirer, mais ce n'est pas la meilleure idée. Vous ne pouvez pas toujours compter sur votre application pour gérer correctement votre base de données, et gérer franchement la base de données ne devrait pas être très préoccupant pour votre application.

Si vous utilisez une base de données relationnelle, il semble alors que vous devriez avoir défini des relations. Malheureusement, cette attitude (vous n'avez pas besoin de clés étrangères) semble être adoptée par de nombreux développeurs d'applications qui préfèrent ne pas s'embarrasser de bêtises telles que l'intégrité des données (mais doivent le faire car leurs entreprises ne disposent pas de développeurs de bases de données dédiés). Habituellement, dans les bases de données assemblées par ces types, vous avez de la chance d’avoir des clés primaires;)

52
AlexCuse

Les clés étrangères sont essentiel à tout modèle de base de données relationnelle.

40
Galwegian

Je les utilise toujours, mais ensuite je crée des bases de données pour les systèmes financiers. La base de données est la partie critique de l'application. Si les données d'une base de données financières ne sont pas totalement exactes, peu importe l'effort que vous déployez dans votre code/conception front-end. Vous ne faites que perdre votre temps.

Il existe également le fait que plusieurs systèmes doivent généralement s’interfacer directement avec la base de données - des systèmes lisant simplement des données (Crystal Reports) aux systèmes insérant des données (sans utiliser nécessairement une API que j’ai conçue; elle peut être écrite par un Gestionnaire ennuyeux qui vient de découvrir VBScript et qui possède le mot de passe SA de la boîte SQL). Si la base de données n’est pas aussi sûre que possible, bon, au revoir, base de données .

Si vos données sont importantes, utilisez des clés étrangères, créez une suite de procédures stockées pour interagir avec les données et créez la base de données la plus robuste possible. Si vos données ne sont pas importantes, pourquoi créez-vous une base de données pour commencer?

29
Ant

Mise à jour : J'utilise toujours les clés étrangères maintenant. Ma réponse à l'objection "ils ont compliqué les tests" est "écrivez vos tests unitaires pour qu'ils n'aient plus besoin de la base de données. Tous les tests utilisant la base de données doivent l'utiliser correctement, y compris les clés étrangères. Si la configuration est pénible, trouver un moyen moins pénible de faire la configuration ".


Les clés étrangères compliquent les tests automatisés

Supposons que vous utilisiez des clés étrangères. Vous écrivez un test automatique qui dit: "lorsque je mets à jour un compte financier, il devrait enregistrer un enregistrement de la transaction". Dans ce test, vous ne vous préoccupez que de deux tables: accounts et transactions.

Cependant, accounts a une clé étrangère à contracts, et contracts a un fk à clients, et clients a un fk à cities, et cities a un fk à states.

Maintenant, la base de données ne vous permettra pas d'exécuter votre test sans configurer des données dans quatre tables non liées à votre test .

Il y a au moins deux perspectives possibles à ce sujet:

  • "C'est une bonne chose: votre test doit être réaliste et ces contraintes de données existeront en production."
  • "C’est une mauvaise chose: vous devriez pouvoir unifier les pièces de test du système sans faire intervenir d’autres pièces. Vous pouvez ajouter des tests d’intégration pour le système dans son ensemble."

Il peut également être possible de désactiver temporairement les vérifications de clés étrangères lors de l'exécution de tests. MySQL, au moins, supporte ceci .

19
Nathan Long

"Ils peuvent rendre la suppression d'enregistrements plus fastidieuse. Vous ne pouvez pas supprimer l'enregistrement" maître "s'il existe des enregistrements dans d'autres tables où des clés étrangères violeraient cette contrainte."

Il est important de se rappeler que le standard SQL définit les actions entreprises lorsqu'une clé étrangère est supprimée ou mise à jour. Ceux que je connais sont:

  • ON DELETE RESTRICT - Empêche la suppression des lignes de l’autre table contenant des clés dans cette colonne. C'est ce que Ken Ray a décrit ci-dessus.
  • ON DELETE CASCADE - Si une ligne de l'autre table est supprimée, supprimez toutes les lignes de cette table qui y font référence.
  • ON DELETE SET DEFAULT - Si une ligne de l'autre table est supprimée, définissez les clés étrangères qui y font référence avec la valeur par défaut de la colonne.
  • ON DELETE SET NULL - Si une ligne de l'autre table est supprimée, définissez les clés étrangères qui y font référence dans cette table sur null.
  • ON DELETE NO ACTION - Cette clé étrangère indique uniquement qu'il s'agit d'une clé étrangère; à utiliser notamment dans les mappeurs OR.

Ces mêmes actions s'appliquent également à ON UPDATE.

La valeur par défaut semble dépendre du serveur sql que vous utilisez.

14
Powerlord

@imphasing - c'est exactement le genre de mentalité qui cause des cauchemars d'entretien.

Pourquoi oh pourquoi voudriez-vous ignorer l’intégrité référentielle déclarative, où les données peuvent être garanties au moins cohérentes, en faveur de la soi-disant "application logicielle" qui est au mieux une mesure préventive faible.

14
Ed Guiness

Il y a une bonne raison de ne pas les utiliser: Si vous ne comprenez pas leur rôle ou comment les utiliser.

Dans les mauvaises situations, les contraintes de clé étrangère peuvent conduire à la reproduction d'accident en cascade. Si quelqu'un supprime le mauvais enregistrement, l'annuler peut devenir une tâche gigantesque.

De même, lorsque vous devez supprimer quelque chose, les contraintes peuvent, si elles sont mal conçues, provoquer toutes sortes de verrous qui vous en empêchent.

12
Kent Fredric

Il n'y a pas de bonnes raisons non de les utiliser ... sauf si les lignes orphelines ne vous intéressent pas beaucoup, je suppose .

11
Matt Rogish

La plus grande question est: conduiriez-vous avec les yeux bandés? C’est comme cela si vous développez un système sans contraintes référentielles. N'oubliez pas que les exigences de l'entreprise changent, les modifications de la conception des applications, les hypothèses logiques respectives dans les modifications du code, la logique elle-même peuvent être refactorisées, etc. En général, les contraintes dans les bases de données sont mises en place sous des hypothèses logiques contemporaines, apparemment correctes pour un ensemble particulier d'assertions et d'hypothèses logiques.

Tout au long du cycle de vie d'une application, la collecte de données de la police via l'application est soumise à des contraintes de contrôle des référentiels et des données, en particulier lorsque de nouvelles exigences entraînent des modifications d'application logiques.

À l'objet de cette liste - Une clé étrangère n'améliore pas en soi les performances, ni ne "dégrade les performances" de manière significative du point de vue du système de traitement des transactions en temps réel. Cependant, il existe un coût agrégé pour la vérification de la contrainte dans le système "batch" à volume élevé. Voici donc la différence entre le processus de transaction en temps réel et par lots; traitement par lots - lorsqu'un coût élevé, engendré par des contrôles de contrainte, d'un lot traité en séquence pose un problème de performances.

Dans un système bien conçu, des vérifications de la cohérence des données seraient effectuées "avant" le traitement d'un lot (il existe néanmoins un coût associé ici également); par conséquent, les contrôles de contrainte de clé étrangère ne sont pas requis pendant le temps de chargement. En fait, toutes les contraintes, y compris la clé étrangère, doivent être temporairement désactivées jusqu'au traitement du lot.

QUERY PERFORMANCE - Si les tables sont jointes sur des clés étrangères, sachez que les colonnes de clé étrangère ne sont PAS INDEXÉES (bien que la clé primaire respective soit indexée par définition). D'ailleurs, en indexant une clé étrangère, en indexant une clé quelconque, et en joignant des tables indexées, on obtient de meilleures performances et non en joignant une clé non indexée avec une contrainte de clé étrangère.

Changement de sujet, si une base de données ne prend en charge que l’affichage/le rendu du contenu de site Web, etc, et l’enregistrement de clics, une base de données avec des contraintes complètes sur toutes les tables est supprimée à ces fins. Pensez-y. La plupart des sites Web n'utilisent même pas de base de données à cet effet. Pour des exigences similaires, où les données sont juste en train d'être enregistrées et non référencées, utilisez une base de données en mémoire, qui n'a pas de contraintes. Cela ne veut pas dire qu’il n’ya pas de modèle de données, oui de modèle logique, mais pas de modèle de données physique.

4
jasbir L

D'après mon expérience, il est toujours préférable d'éviter d'utiliser des FK dans les applications critiques de bases de données. Je ne voudrais pas être en désaccord avec les gars ici qui disent que les FK sont une bonne pratique mais ce n’est pas pratique lorsque la base de données est énorme et comporte d’énormes opérations CRUD/sec. Je peux partager sans nommer ... l'une des plus grandes banques d'investissement du monde n'a pas un seul FK dans ses bases de données. Ces contraintes sont gérées par les programmeurs lors de la création d'applications impliquant une base de données. La raison fondamentale est que chaque fois qu'un nouveau CRUD est créé, il doit effectuer plusieurs tables et vérifier pour chaque insertion/mise à jour, bien que cela ne soit pas un gros problème pour les requêtes affectant des lignes uniques, mais que cela crée une latence énorme lorsque vous traitez traitement par lots que toute grande banque doit effectuer au quotidien.

Il vaut mieux éviter les FK, mais le risque doit être pris en charge par les programmeurs.

3
Rachit

"Avant d’ajouter un enregistrement, vérifiez qu’un enregistrement correspondant existe dans une autre table" est la logique applicative.

Voici quelques raisons pour lesquelles vous ne voulez pas cela dans la base de données:

  1. Si les règles commerciales changent, vous devez changer la base de données. La base de données devra recréer l'index dans de nombreux cas, ce qui est lent pour les grandes tables. (Les règles changeantes incluent: autoriser les invités à poster des messages ou autoriser les utilisateurs à supprimer leur compte malgré les commentaires postés, etc.).

  2. La modification de la base de données n’est pas aussi simple que le déploiement d’un correctif logiciel en transmettant les modifications au référentiel de production. Nous voulons éviter de modifier autant que possible la structure de la base de données. Plus il y a de logique métier dans la base de données, plus vous augmentez les chances de devoir modifier le databae (et de déclencher une réindexation).

  3. TDD. Dans les tests unitaires, vous pouvez remplacer la base de données par des bases factices et tester la fonctionnalité. Si vous avez une logique métier dans votre base de données, vous ne réalisez pas de tests complets et vous devez soit tester avec la base de données, soit reproduire la logique métier dans le code à des fins de test. de la même façon.

  4. Réutiliser votre logique avec différentes sources de données. S'il n'y a pas de logique dans la base de données, mon application peut créer des objets à partir d'enregistrements de la base de données, à partir d'un service Web, d'un fichier JSON ou de toute autre source. Je dois juste échanger la mise en œuvre du mappeur de données et utiliser toute ma logique métier avec n'importe quelle source. S'il existe une logique dans la base de données, cela n'est pas possible et vous devez implémenter la logique au niveau de la couche de mappeur de données ou dans la logique métier. De toute façon, vous avez besoin de ces contrôles dans votre code. S'il n'y a pas de logique dans la base de données, je peux déployer l'application dans différents emplacements en utilisant différentes implémentations de base de données ou de fichiers plats.

3
Tom B

Raison supplémentaire d'utiliser des clés étrangères: - Permet une plus grande réutilisation d'une base de données

Raison supplémentaire de NE PAS utiliser de clés étrangères: - Vous essayez de verrouiller un client dans votre outil en réduisant la réutilisation.

3
Dan

Je suis d'accord avec les réponses précédentes en ce qu'elles sont utiles pour maintenir la cohérence des données. Cependant, il y a quelques semaines, article intéressant de Jeff Atwood a discuté des avantages et des inconvénients des données normalisées et cohérentes.

En quelques mots, une base de données dénormalisée peut être plus rapide lors du traitement de grandes quantités de données; et vous pouvez ne pas vous soucier de la cohérence précise en fonction de l'application, mais cela vous oblige à être beaucoup plus prudent lorsque vous traitez des données, car la base de données ne le sera pas.

2
Santiago Palladino

La base de données Clarify est un exemple de base de données commerciale qui ne contient aucune clé primaire ou étrangère.

http://www.geekinterview.com/question_details/18869

Ce qui est amusant, c’est que la documentation technique explique très bien comment les tables sont liées, quelles colonnes utiliser pour les joindre, etc.

En d’autres termes, ils auraient pu avoir joint les tables avec des déclarations explicites (DRI), mais ils ont choisi de ne pas le faire .

Par conséquent, la base de données Clarify est pleine d’incohérences et elle est sous-performante.

Mais je suppose que cela simplifiait le travail des développeurs, car il n'était plus nécessaire d'écrire du code pour gérer l'intégrité référentielle, comme la vérification des lignes associées avant la suppression, l'ajout.

Et c’est, je pense, le principal avantage de ne pas avoir de contrainte de clé étrangère dans une base de données relationnelle. Cela facilite le développement, du moins du point de vue du diable.

2
Ed Guiness

Je ne connais que les bases de données Oracle, pas d'autres, et je peux dire que les clés étrangères sont essentielles au maintien de l'intégrité des données. Avant d’insérer des données, une structure de données doit être créée et corrigée. Lorsque cela est fait - et donc toutes les clés primaires ET étrangères sont créées - le travail est terminé!

Signification: lignes orphelines? Non, jamais vu ça dans ma vie. Sauf si un mauvais programmeur a oublié la clé étrangère ou s'il l'a implémentée à un autre niveau. Les deux sont - dans le contexte d’Oracle - d’énormes erreurs, qui conduiront à la duplication de données, aux données orphelines, et donc à la corruption des données. Je ne peux pas imaginer une base de données sans FK forcé. Cela ressemble à du chaos pour moi. C'est un peu comme le système de permission Unix: imaginez que tout le monde soit root. Pensez au chaos.

Les clés étrangères sont essentielles, tout comme les clés primaires. C'est comme dire: et si on retirait les clés primaires? Eh bien, le chaos total va se passer. C'est ce que. Vous ne pouvez pas déplacer la responsabilité de la clé primaire ou étrangère au niveau de la programmation, mais au niveau des données.

Désavantages ? Oui absolument ! Parce qu’en insertion, il y aura beaucoup plus de vérifications. Mais si l'intégrité des données est plus importante que la performance, c'est une évidence. Le problème de performance sur Oracle est davantage lié aux index, qui viennent avec PK et FK.

2
tvCa

Ils peuvent rendre la suppression d'enregistrements plus fastidieuse - vous ne pouvez pas supprimer l'enregistrement "maître" s'il existe des enregistrements dans d'autres tables où des clés étrangères violeraient cette contrainte. Vous pouvez utiliser des déclencheurs pour effectuer des suppressions en cascade.

Si vous avez choisi votre clé primaire à mauvais escient, la modification de cette valeur devient encore plus complexe. Par exemple, si le PK de ma table "clients" est le nom de la personne et que cette clé est définie comme FK dans la table "orders", si le client veut changer de nom, il s'agit alors d'une douleur royale. .mais c'est juste la conception de base de données de mauvaise qualité.

Je pense que les avantages de l’utilisation de clés Fireign l’emportent sur les inconvénients supposés.

1
Ken Ray

Je dois appuyer la plupart des commentaires ici. Les clés étrangères sont des éléments nécessaires pour garantir l’intégrité des données. Les différentes options pour ON DELETE et ON UPDATE vous permettront de contourner certaines des "chutes" que les gens mentionnent ici concernant leur utilisation.

Je constate que dans 99% de mes projets, des FK seront chargés de renforcer l'intégrité des données. Cependant, il existe de rares occasions où j'ai des clients qui DOIVENT conserver leurs anciennes données, quelle que soit leur gravité .... mais ensuite, je passe beaucoup de temps à écrire du code qui, de toute façon, n'obtient que les données valides, de sorte qu'il devient inutile.

1
Mitchel Sellers

L’argument que j’ai entendu est que le front-end devrait avoir ces règles de gestion. Les clés étrangères "ajoutent une surcharge inutile" lorsque vous ne devriez pas autoriser des insertions qui rompent vos contraintes en premier lieu. Est-ce que je suis d'accord avec ça? Non, mais c'est ce que j'ai toujours entendu dire.

EDIT: Je suppose qu'il faisait référence à des contraintes de clé étrangère , et non à des clés étrangères en tant que concept.

1
lordscarlet

La vérification des contraintes de clé étrangère prend un certain temps, de sorte que certaines personnes omettent les clés étrangères pour obtenir des performances supplémentaires.

1
remonedo

Si vous êtes absolument certain que le système de base de données sous-jacent ne changera pas à l'avenir, j'utiliserais des clés étrangères pour garantir l'intégrité des données.

Mais voici une autre très bonne raison de ne pas utiliser de clé étrangère du tout:

Vous développez un produit qui devrait prendre en charge différents systèmes de base de données.

Si vous travaillez avec Entity Framework, qui peut se connecter à de nombreux systèmes de base de données, vous pouvez également vouloir prendre en charge des bases de données sans serveur "à source ouverte et gratuite". Toutes ces bases de données ne peuvent pas prendre en charge vos règles de clé étrangère (mise à jour, suppression de lignes, etc.).

Cela peut entraîner différents problèmes:

1.) Vous pouvez rencontrer des erreurs lorsque la structure de la base de données est créée ou mise à jour. Peut-être n'y aura-t-il que des erreurs silencieuses, car vos clés étrangères sont simplement ignorées par le système de base de données.

2.) Si vous utilisez des clés étrangères, vous ferez probablement moins, voire aucune vérification de l'intégrité des données dans votre logique métier. Désormais, si le nouveau système de base de données ne prend pas en charge ces règles de clé étrangère ou se comporte simplement différemment, vous devez réécrire votre logique métier.

Vous pouvez demander: Qui a besoin de différents systèmes de base de données? Tout le monde ne peut se permettre ni ne veut un serveur SQL complet sur sa machine. Ceci est un logiciel, qui doit être maintenu. D'autres ont déjà investi du temps et de l'argent dans un autre système de base de données. Les bases de données sans serveur conviennent parfaitement aux petits clients sur une seule machine.

Personne ne sait comment se comportent tous ces systèmes de base de données, mais votre logique métier, avec des contrôles d'intégrité, reste toujours la même.

1
Michael

Je fais écho à la réponse de Dmitriy - très bien exprimé.

Pour ceux qui s'inquiètent de la surcharge de performances souvent apportée par les FK, il existe un moyen (dans Oracle) d'obtenir l'avantage de l'optimiseur de requête de la contrainte FK sans les coûts supplémentaires de la validation de contrainte lors de l'insertion, de la suppression ou de la mise à jour. Cela consiste à créer la contrainte FK avec les attributs RELY DISABLE NOVALIDATE. Cela signifie que l'optimiseur de requête ASSUME que la contrainte a été appliquée lors de la création de requêtes, sans que la base de données applique réellement la contrainte. Vous devez faire très attention ici à prendre la responsabilité lorsque vous remplissez une table avec une contrainte FK telle que celle-ci afin de vous assurer absolument que la ou les colonnes FK ne contiennent pas de données ne respectant pas la contrainte, comme si vous le faisiez. pourrait obtenir des résultats non fiables des requêtes impliquant la table sur laquelle cette contrainte FK est activée.

J'utilise généralement cette stratégie sur certaines tables de mon schéma de magasin de données, mais pas dans mon schéma de stockage intermédiaire intégré. Je m'assure que la même contrainte est appliquée aux tables à partir desquelles je copie des données, ou que la routine ETL applique la contrainte.

1
Mike McAllister

J'ai également entendu cet argument - de personnes qui ont oublié de mettre un index sur leurs clés étrangères, puis qui se sont plaintes de la lenteur de certaines opérations (car la vérification de la contrainte pouvait tirer parti de tout index). Donc, pour résumer: Il n'y a aucune bonne raison de ne pas utiliser de clés étrangères. Toutes les bases de données modernes supportent les suppressions en cascade, donc ...

1
Arno

Pour moi, si vous voulez respecter les normes ACIDE , il est essentiel de disposer de clés étrangères pour assurer l’intégrité référentielle.

1
CodeRot

Beaucoup de personnes qui répondent ici sont trop attachées à l’importance de l’intégrité référentielle mise en œuvre via des contraintes référentielles. Travailler sur des bases de données volumineuses avec une intégrité référentielle ne fonctionne tout simplement pas bien. Oracle semble particulièrement mauvais pour les suppressions en cascade. Ma règle empirique est que les applications ne doivent jamais mettre à jour directement la base de données et doivent se faire via une procédure stockée. Cela conserve la base de code dans la base de données et signifie que la base de données conserve son intégrité.

Lorsque de nombreuses applications peuvent accéder à la base de données, des problèmes surviennent en raison de contraintes d'intégrité référentielle, mais il s'agit d'un contrôle.

Il existe également un problème plus vaste en ce sens que les développeurs d'applications peuvent avoir des exigences très différentes avec lesquelles les développeurs de bases de données ne sont pas nécessairement familiarisés.

1
Zak

Je pense aussi que les clés étrangères sont une nécessité dans la plupart des bases de données. Le seul inconvénient (outre l'impact sur les performances lié à la cohérence forcée) est que la clé étrangère permet aux utilisateurs d'écrire du code supposant qu'il existe une clé étrangère fonctionnelle. Cela ne devrait jamais être autorisé.

Par exemple, j'ai vu des personnes écrire du code qui s'insère dans la table référencée puis tente de l'insérer dans la table de référence sans vérifier que la première insertion a réussi. Si la clé étrangère est supprimée ultérieurement, la base de données est incohérente.

Vous n'avez pas non plus la possibilité d'assumer un comportement spécifique lors de la mise à jour ou de la suppression. Vous devez toujours écrire votre code pour faire ce que vous voulez, qu'il y ait ou non une clé étrangère. Si vous supposez que les suppressions sont en cascade alors qu'elles ne le sont pas, vos suppressions échoueront. Si vous supposez que les mises à jour des colonnes référencées sont propagées aux lignes de référencement alors qu'elles ne le sont pas, vos mises à jour échoueront. Aux fins de l'écriture de code, vous pouvez également ne pas avoir ces fonctionnalités.

Si ces fonctionnalités sont activées, votre code les imitera quand même et vous perdrez un peu de performance.

Donc, le résumé ... Les clés étrangères sont essentielles si vous avez besoin d’une base de données cohérente. Les clés étrangères ne doivent jamais être considérées comme présentes ou fonctionnelles dans le code que vous écrivez.

1
Eric

Wowowo ...
Réponses partout. En fait, c’est le sujet le plus compliqué que j’ai jamais rencontré. J'utilise des FK lorsque cela est nécessaire, mais dans un environnement de production, je les utilise rarement.

Voici pourquoi j'utilise rarement les Fks:

1. La plupart du temps, je traite d’énormes données sur un petit serveur afin d’améliorer les performances et de supprimer les FK. Parce que quand vous avez des FK et que vous créez, mettez à jour ou supprimez le SGBDR, commencez par vérifier s’il n’ya pas de violation de contrainte et si vous avez une base de données énorme qui pourrait être fatale

2. Parfois, j'ai besoin d'importer des données d'autres lieux et comme je ne suis pas trop sûr de leur structure, je laisse simplement tomber les FK.

3. Si vous utilisez plusieurs bases de données et que la clé de référence dans une autre base de données ne fonctionnera pas bien (comme pour le moment) tant que vous n'avez pas supprimé les FK (relations entre bases de données).
4. C’est également le cas lorsque vous écrivez une application qui figure sur un SGBDR quelconque ou que vous souhaitez que votre base de données soit exportée et importée dans n’importe quel système SGBDR. Dans ce cas, chaque système SGBDR spécifique a sa propre manière de traiter les FK et vous serez probablement obligé d'abandonner l'utilisation des FK.

5. Si vous utilisez une plateforme de SGBDR (ORM), vous savez que certains d'entre eux proposent leur propre mappage en fonction de la solution et de la technicité de leur offre et vous ne vous souciez pas de la création des tables et de leurs FK.

6. Avant le dernier point, vous aurez la connaissance nécessaire pour gérer une base de données contenant des FK et la possibilité d’écrire une application qui exécute tout le travail sans recourir à FK 7. Enfin, j’ai commencé à le dire, tout dépend de votre scénario. une barrière. Vous aurez toujours envie de courir le meilleur des meilleurs que vous pouvez obtenir!


Merci tout le monde!

Un problème particulier lié à l'utilisation d'un FK peut survenir lorsque vous disposez de données historiques qui référencent la clé (dans une table de recherche), même si vous ne souhaitez plus que la clé soit disponible.
Évidemment, la solution consiste à concevoir les choses mieux à l’avance, mais je pense à des situations concrètes dans lesquelles vous n’avez pas toujours le contrôle de la solution complète.
Par exemple: vous avez peut-être une table de consultation customer_type qui répertorie différents types de clients - disons que vous devez supprimer un certain type de client, mais (en raison de contraintes commerciales), vous ne pouvez pas mettre à jour le logiciel client, et personne n’a envisagé cette situation lors du développement du logiciel, le fait que c'est une clé étrangère dans une autre table qui peut vous empêcher de supprimer la ligne même si vous connaissez les données historiques qui la référence n'est pas pertinente.
Après avoir été brûlé plusieurs fois avec cela, vous vous écartez probablement de l'application des relations par la base de données.
(Je ne dis pas que c'est bon - donnez simplement une raison pour laquelle vous pouvez décider d'éviter les contraintes FK et db en général)

0
hamishmcn

Dans un projet sur lequel j'ai travaillé, il existait souvent des relations implicites plutôt qu'explicites, de sorte que de nombreuses tables pouvaient être jointes sur la même colonne.

Prenez le tableau suivant

Adresse

  • AddressId (PK)
  • EntityId
  • Type d'entité
  • Ville
  • Etat
  • Pays
  • Etc..

Les valeurs possibles d'EntityType peuvent être Employé, Société, Client, et EntityId fait référence à la clé primarky de la table qui vous intéressait.

Je ne pense pas vraiment que ce soit la meilleure façon de faire les choses, mais cela a fonctionné pour ce projet.

0
Curtis

Comme beaucoup de choses, c'est un compromis. C'est une question de savoir où vous voulez faire le travail pour vérifier l'intégrité des données:

(1) utiliser une clé étrangère (un seul point à configurer pour une table, cette fonctionnalité est déjà implémentée, testée et éprouvée)

(2) le laisser aux utilisateurs de la base de données (plusieurs utilisateurs/applications possibles mettant à jour le ou les mêmes tableaux, ce qui signifie davantage de points de défaillance potentiels et une complexité accrue des tests).

La base de données est plus efficace (2), plus facile à gérer et moins risquée avec (1).

0
Jen A

Je vais faire écho à ce que Dmitriy a dit, mais en ajoutant un point.

J'ai travaillé sur un système de facturation par lots qui devait insérer de grands ensembles de lignes sur plus de 30 tables. Nous n'étions pas autorisés à faire une pompe de données (Oracle), nous avons donc dû faire des insertions en bloc. Ces tables avaient des clés étrangères, mais nous nous étions déjà assurés qu'elles ne rompaient aucune relation.

Avant l'insertion, nous désactivons les contraintes de clé étrangère afin que Oracle ne prenne pas toujours les insertions. Une fois l’insertion réussie, nous réactivons les contraintes.

PS: Dans une base de données volumineuse contenant de nombreuses clés étrangères et de nombreuses lignes enfant pour un seul enregistrement, il arrive que les clés étrangères soient incorrectes et que vous souhaitiez peut-être interdire les suppressions en cascade. Pour nous dans le système de facturation, cela prendrait trop de temps et serait trop pénible pour la base de données si nous effectuions des suppressions en cascade. Nous marquons donc l'enregistrement comme défectueux avec un champ dans la table du pilote principal (parent).

0
typicalrunt

Dans DB2, si des tables de requête matérialisées (MQT) sont utilisées, des contraintes de clé étrangère sont nécessaires pour que l'optimiseur puisse choisir le bon plan pour une requête donnée. Comme elles contiennent les informations de cardinalité, l'optimiseur utilise fortement les métadonnées pour utiliser un MQT ou non.

0
Senthil

Un bon principe de la conception de la structure de données consiste à s'assurer que chaque attribut d'une table ou d'un objet est soumis à une contrainte bien comprise. Ceci est important car si vous ou votre programme pouvez compter sur des données valides dans la base de données, vous êtes moins susceptible d'avoir des défauts de programme causés par de mauvaises données. De plus, vous passez moins de temps à écrire du code pour gérer les conditions d'erreur et vous êtes plus susceptible d'écrire du code de traitement des erreurs dès le départ.

Dans de nombreux cas, ces contraintes peuvent être définies au moment de la compilation. Dans ce cas, vous pouvez écrire un filtre pour vous assurer que l'attribut se trouve toujours dans la plage ou que la tentative de sauvegarde de l'attribut échoue.

Cependant, dans de nombreux cas, ces contraintes peuvent changer au moment de l'exécution. Par exemple, vous pouvez avoir un tableau "voitures" ayant pour attribut "couleur" qui prend initialement les valeurs, par exemple "rouge", "vert" et "bleu". Lors de l'exécution du programme, il est possible d'ajouter des couleurs valides à cette liste initiale. De nouvelles "voitures" ajoutées peuvent prendre n'importe quelle couleur de la liste de couleurs à jour. De plus, vous voulez généralement que cette liste de couleurs mise à jour survive au redémarrage du programme.

Pour répondre à votre question, il s'avère que si vous avez besoin de contraintes de données qui peuvent changer au moment de l'exécution, et que ces modifications doivent survivre au redémarrage du programme, les clés étrangères constituent la solution la plus simple et la plus concise au problème. Le coût de développement correspond à l'ajout d'une table (par exemple, "couleurs", d'une contrainte de clé étrangère à la table "voitures" et d'un index), et le coût d'exécution correspond à la recherche supplémentaire dans la table pour les couleurs mises à jour. pour valider les données, et ce coût d'exécution est généralement atténué par l'indexation et la mise en cache.

Si vous n'utilisez pas de clés étrangères pour ces besoins, vous devez écrire un logiciel pour gérer la liste, rechercher des entrées valides, l'enregistrer sur un disque, structurer efficacement les données si la liste est volumineuse, assurez-vous que les mises à jour de la liste ne corrompre le fichier de liste, fournir un accès série à la liste au cas où il y aurait plusieurs lecteurs et/ou rédacteurs, etc. c'est-à-dire que vous devez implémenter de nombreuses fonctionnalités du SGBDR.

0
Jay Godse

J'ai toujours pensé qu'il était paresseux de ne pas les utiliser. On m'a appris que cela devrait toujours être fait. Mais ensuite, je n'ai pas écouté la discussion de Joel. Il a peut-être eu une bonne raison, je ne sais pas.

0
Kilhoffer

Q uite nous recevons souvent les erreurs avec contraintes FK Impossible d'ajouter ou de mettre à jour une ligne enfant: une contrainte de clé étrangère échoue Supposons qu'il y en ait deux tables inventory_source et contract_lines, et nous référons inventory_source_id dans contract_lines à partir de inventory_source et supposons que nous voulions supprimer un enregistrement de inventory_source et que l'enregistrement soit déjà présent dans contract_lines ou si nous voulons supprimer la colonne PK de la table Base, nous obtenons des erreurs pour les contraintes FK, nous pouvons l'éviter en utilisant les étapes décrites ci-dessous.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

Nous pouvons le surmonter en utilisant les étapes suivantes: -

  1. Supprimer ou mettre à jour la ligne de la source Inventory supprime ou met à jour automatiquement les lignes correspondantes dans la table contract_lines. Cette opération est appelée suppression ou mise à jour en cascade.
  2. Une autre façon de procéder consiste à définir la colonne i.e InventorySource_ID dans la table contract_lines sur NULL, lorsqu'un enregistrement correspondant à celui-ci est supprimé de la table Inventoryource.
  3. Nous pouvons restreindre la table parent pour la suppression ou la mise à jour, autrement dit, il est possible de rejeter l'opération de suppression ou de mise à jour de la table inventory_source.
  4. Toute tentative de suppression ou de mise à jour d'une valeur de clé primaire ne sera pas autorisée s'il existe une valeur de clé étrangère associée dans la table référencée.
0
Vikas Kukreti