web-dev-qa-db-fra.com

Pourquoi les clés étrangères sont-elles plus utilisées en théorie qu'en pratique?

Lorsque vous étudiez la théorie relationnelle, les clés étrangères sont bien sûr obligatoires. Mais en pratique, partout où j'ai travaillé, les produits de table et les jointures se font toujours en spécifiant explicitement les clés dans la requête, au lieu de s'appuyer sur des clés étrangères dans le SGBD.

De cette façon, vous pouvez bien sûr joindre deux tables par des champs qui ne sont pas censés être des clés étrangères, ce qui donne des résultats inattendus.

Pourquoi pensez-vous que c'est? Les SGBD ne devraient-ils pas exiger que les jointures et les produits soient créés uniquement à l'aide de clés étrangères?

EDIT: Merci pour toutes les réponses. Il est clair pour moi maintenant que la raison principale des FK est l’intégrité de référence. Mais si vous concevez une base de données, toutes les relations du modèle (flèches I.E. dans la DRE) deviennent des clés étrangères, du moins en théorie, que vous les définissiez ou non comme telles dans votre SGBD, ce sont sémantiquement des FK. Je ne peux pas imaginer la nécessité de joindre des tables par des champs non FK. Quelqu'un peut-il donner un exemple qui a du sens?

PS: Je suis conscient du fait que les relations N: M deviennent des tables séparées et non des clés étrangères, elles sont simplement omises pour des raisons de simplicité.

48
Petruza

La raison pour laquelle les contraintes de clé étrangère existent est de garantir que les lignes référencées existent.

"La clé étrangère identifie une colonne ou un ensemble de colonnes dans une table qui fait référence à une colonne ou à un ensemble de colonnes dans une autre table. Les valeurs d'une ligne des colonnes référencées doivent figurer sur une seule ligne de la table référencée. 

Ainsi, une ligne de la table de référence ne peut pas contenir de valeurs qui n'existent pas dans la table référencée (sauf potentiellement NULL). De cette façon, il est possible de faire des liens pour lier des informations et il s’agit d’un élément essentiel de la normalisation de la base de données. "( Wikipedia )


RE: Votre question: "Je ne peux pas imaginer la nécessité de joindre des tables avec des champs non FK":

Lors de la définition d'une contrainte de clé étrangère, la ou les colonnes de la table de référence doivent être la clé primaire de la table référencée ou au moins une clé candidate.

Lors de jointures, il n'est pas nécessaire de joindre des clés primaires ou des clés candidates.

Voici un exemple qui pourrait avoir un sens:

CREATE TABLE clients (
    client_id       uniqueidentifier  NOT NULL,
    client_name     nvarchar(250)     NOT NULL,
    client_country  char(2)           NOT NULL
);

CREATE TABLE suppliers (
    supplier_id       uniqueidentifier  NOT NULL,
    supplier_name     nvarchar(250)     NOT NULL,
    supplier_country  char(2)           NOT NULL
);

Et puis interrogez comme suit:

SELECT 
    client_name, supplier_name, client_country 
FROM 
    clients 
INNER JOIN
    suppliers ON (clients.client_country = suppliers.supplier_country)
ORDER BY
    client_country;

Ces jointures sont également utiles dans les bases de données offrant des fonctionnalités géospatiales, telles que SQL Server 2008 ou Postgres avec PostGIS. Vous pourrez faire des requêtes comme celles-ci:

SELECT
    state, electorate 
FROM 
    electorates 
INNER JOIN 
    postcodes on (postcodes.Location.STIntersects(electorates.Location) = 1);

Source: ConceptDev - Géographie de SQL Server 2008: STIntersects, STArea

Vous pouvez voir un autre exemple géospatial similaire dans la réponse acceptée à l'article " problème de requête SQL 2008 - quel LatLong existe dans un polygone géographique? ":

SELECT 
    G.Name, COUNT(CL.Id)
FROM
    GeoShapes G
INNER JOIN 
    CrimeLocations CL ON G.ShapeFile.STIntersects(CL.LatLong) = 1
GROUP BY 
    G.Name;

Ce sont toutes des jointures SQL valides qui n'ont rien à voir avec les clés étrangères et les clés candidates et qui peuvent toujours être utiles dans la pratique.

39
Daniel Vassallo

Les clés étrangères ont moins à voir avec les jointures qu'avec la préservation de l'intégrité de la base de données. La preuve en est que vous pouvez joindre des tables comme vous le souhaitez, même si cela n’a pas de sens.

34
Otávio Décio

Je ne peux pas imaginer la nécessité de joindre des tables par des champs qui ne sont pas des FK. Quelqu'un peut-il donner un exemple qui a du sens?

FOREIGN KEYs ne peut être utilisé pour appliquer l'intégrité référentielle que si la relation entre les entités du modèle ER est reflétée avec un équijoint entre deux relations dans le modèle relationnel.

Ce n'est pas toujours vrai.

Voici un exemple de l'article de mon blog que j'ai écrit il y a quelque temps:

Ce modèle décrit les biens et les fourchettes de prix:

Et voici l'implémentation relationnelle du modèle:

CREATE TABLE Goods (ID, Name, Price)
CREATE TABLE PriceRange (Price, Bonus)

Comme vous pouvez le constater, la table PriceRange n'a qu'un seul attribut lié au prix, Price, mais le modèle en a deux: StartPrice et EndPrice.

En effet, le modèle relationnel permet de transformer les ensembles et l'entité PriceRange peut être facilement reconstruite à l'aide des opérations SQL.

Goods
ID  Name               Price
1   Wormy Apple        0.09
2   Bangkok durian     9.99
3   Densuke watermelon 999.99
4   White truffle      99999.99

PriceRange
Price   Bonus
0.01       1%
1.00       3%
100.00    10%
10000.00  30%

Nous stockons uniquement la limite inférieure de chaque plage. La limite supérieure peut facilement être déduite.

Voici la requête pour trouver le bonus pour chaque bien:

SELECT  *
FROM    Goods
JOIN    PriceRange
ON      PriceRange.Price =
        (
        SELECT  MAX(Price)
        FROM    PriceRange
        WHERE   PriceRange.Price <= Goods.Price
        )

Nous voyons que ce modèle relationnel implémente assez bien le modèle ER, mais aucune clé étrangère ne peut être déclarée entre ces relations, car l'opération utilisée pour les lier n'est pas une équijointure.

10
Quassnoi

Non, l'application n'est pas nécessaire. cela interdirait certaines fonctionnalités utiles, telles que la surcharge éventuelle des colonnes. Bien que ce type d'utilisation ne soit pas idéal, il IS est utile dans certaines situations réelles.

L'utilisation appropriée des contraintes de clé étrangère est juste comme ça; une contrainte sur les valeurs ajoutées à une colonne donnée qui assure que leurs lignes référencées existent.

Il convient de noter qu'un manque important de contraintes de clé étrangère sur un schéma donné constitue une mauvaise "odeur" et peut indiquer de graves problèmes de conception.

8
Paul Sonier

Vous pouvez rejoindre n'importe quelle expression. Que vous définissiez ou non des clés étrangères dans votre base de données est sans importance. Les clés étrangères contraignent INSERT/UPDATE/DELETE, pas SELECT.

Alors pourquoi beaucoup de projets ignorent-ils la définition de clés étrangères? Il existe plusieurs raisons:

  • Le modèle de données est mal conçu et nécessite des références brisées (exemples: associations polymorphes, EAV).

  • Les codeurs ont peut-être entendu dire que "les clés étrangères sont lentes", alors ils les abandonnent. En fait, le travail supplémentaire que vous devez faire pour assurer la cohérence des données lorsque vous ne pouvez pas compter sur des clés étrangères rend votre application beaucoup moins efficace. L'optimisation prématurée sans mesurer réellement le bénéfice est un problème courant.

  • Les contraintes entravent certaines tâches de nettoyage des données. Parfois, vous avez besoin de casser les références temporairement lorsque vous modifiez les données. Beaucoup de SGBDR permettent de désactiver les contraintes, mais parfois les programmeurs décident qu'il est plus facile de les laisser les désactiver. S'il est souvent nécessaire de désactiver les contraintes, cela indique probablement une conception de base de données gravement endommagée.

6
Bill Karwin

Les clés étrangères utilisées de la manière que vous décrivez ne sont pas comment elles sont censées être utilisées. Ils sont destinés à garantir que si un enregistrement dépend logiquement d'un enregistrement correspondant existant ailleurs, cet enregistrement correspondant est bien présent.

Je pense que si les développeurs/dbas ont le temps de choisir un (A) bon nom de développeur pour leurs tables et leurs champs, ou bien (B) de définir des contraintes de clé étrangère étendues, l’optionAest le choix facile. J'ai travaillé dans les deux situations. Lorsque des contraintes importantes sont maintenues pour maintenir l'ordre et empêcher les gens de tout gâcher, les choses peuvent vraiment devenir un gâchis.

Il faut beaucoup d'efforts pour tenir à jour toutes vos contraintes de clé étrangère pendant le développement, temps que vous pourriez consacrer à d'autres tâches de grande valeur pour lesquelles vous avez à peine du temps. En revanche, dans les situations où vous avez de bonnes conventions de dénomination, les clés étrangères sont immédiatement claires. Les développeurs n'ont pas besoin de rechercher des clés étrangères ou d'essayer une requête pour voir si cela fonctionne. ils peuvent juste voir les relations.

Je pense que les contraintes de clé étrangère deviennent rapidement utiles au fur et à mesure que le nombre d'équipes différentes utilisant une base de données augmente. Il devient difficile d'appliquer une dénomination cohérente; la connaissance de la base de données devient fragmentée; Il est facile pour les actions de base de données d'avoir des conséquences inattendues pour une autre équipe.

3
Patrick Karcher

Car en pratique, la théorie ne suffit pas;)

Sérieusement, selon mon expérience, c'est principalement parce que la théorie n'est pas assez souple pour prendre en compte toutes les possibilités que vous devez gérer dans le monde réel. Seulement avec un cas extrêmement bizarre que vous devez stocker dans votre base de données (ou quelque chose de plus courant, comme une surcharge de colonnes), vous devez extraire le FK et l'implémenter dans le DAL. 

Peut-être que vous pouvez développer une solution qui peut être archivée de manière totalement normalisée (par exemple), mais dans de nombreux cas, le travail requis et/ou les résultats finaux ne valent pas la peine.

Mes deux centimes.

3
j.a.estevan

Les SGBD sont conçus pour permettre le plus grand nombre de solutions tout en respectant leurs règles fondamentales.

Limiter les jointures à des clés étrangères définies limiterait énormément les fonctionnalités, d'autant plus que la plupart des développements ne se font pas avec un administrateur de base de données dédié ou une révision de procédures SQL/stockées.

Cela dit, en fonction de votre couche d'accès aux données, vous devrez peut-être configurer des clés étrangères pour utiliser les fonctionnalités. Par exemple, Linq to SQL.

2
Bravax

Les clés étrangères ne sont pas utilisées aussi souvent que la théorie relationnelle le suggère, car les personnes de type relationnel/relationnel n'écrivent pas une grande partie du code et ne conçoivent même pas les tables. Les programmeurs écrivent les tables de code/conception ou ont une grande influence sur la conception de ces tables.

2
ElGringoGrande

Sur quel type d'applications de base de données travaillez-vous? La théorie que vous voyez souvent concerne l’utilisation de la base de données raw, auquel cas les contraintes peuvent être très utiles. En pratique, les bases de données sont souvent utilisées comme back-end d'applications plus volumineuses. Dans de nombreux cas, ces applications doivent valider les transactions elles-mêmes et il serait inutile de les répéter dans la base de données.

Considérons une application de vente, par exemple. Lorsque quelqu'un passe une commande, il va peut-être rechercher le client dans la base de données pour obtenir l'adresse ou les informations de carte de crédit. Lorsqu'il ne trouve pas de client, il sera programmé pour faire quelque chose de raisonnable. S'il attendait jusqu'à ce qu'il tente d'insérer une ligne dans la table des commandes pour découvrir qu'il n'y avait pas de client, les retours seraient moins rapides et moins pratiques.

Quelque chose doit préserver l'intégrité de la base de données, mais le faire dans le SGBD lui-même n'est pas toujours la meilleure solution.

2
David Thornley

Je programme depuis quelques décennies, bien avant que les bases de données relationnelles ne deviennent la norme. Lorsque j'ai commencé à travailler avec MySQL et que j'apprenais moi-même PHP, j'ai vu l'option Clé étrangère et la toute première pensée a été "Wow! C'est retardé". La raison pour laquelle seulement un imbécile croit que le laboratoire dicte la réalité. Il devint immédiatement évident que, sauf si vous codiez une application qui ne serait jamais modifiée, jamais , vous encapsulerez votre application dans une fonte d'acier où la seule option est de créer plus de tables ou de créer des solutions créatives.

Cette évaluation initiale était née de chaque application de production du monde réel que j'ai rencontrée. Non seulement la contrainte ralentit considérablement toutes les modifications, mais elle rend presque impossible le développement de l’application, indispensable pour une entreprise.

La seule raison pour laquelle je n'ai jamais trouvé de contraintes sur les tables est les codeurs paresseux. Pas disposé à écrire du code propre pour vérifier l'intégrité des données. 

Michael

2
Michael

Les clés étrangères sont extrêmement importantes, en particulier dans les bases de données sur lesquelles des requêtes manuelles sont exécutées ou pour lesquelles un logiciel est activement développé. Toute requête non testée exécutée sur la base de données a la possibilité de contenir une erreur. Les contraintes telles que les clés étrangères servent à mettre en évidence ces erreurs avant que les données ne soient incohérentes.

Ces contraintes sont appliquées par le concepteur du schéma et garantissent que les données restent dans le modèle qu'il a envisagé. Si les contraintes n'existent pas, une requête introduira tôt ou tard une certaine incohérence. Une incohérence conduira à des résultats imprévisibles à partir de requêtes et est très difficile à inverser.

1
Paul

Une partie de cela pour moi est que (et oui, c'est une excuse boiteuse) l'interface utilisateur dans le studio de gestion de SQL Server de MS pour ajouter des clés étrangères est terrible

Une clé étrangère est une contrainte selon laquelle "toute valeur de la colonne x de la table a doit apparaître dans la colonne y de la table b", mais l'interface utilisateur permettant de la spécifier dans SSMS n'indique pas clairement la table avec laquelle vous dérangez. table parent, qui est la table enfant, et ainsi de suite. 

Chaque fois que je devais créer une clé étrangère, c'était un essai et une erreur jusqu'à ce que cela semble fonctionner.

0
Aric TenEyck

Bonne question. Je me suis toujours demandé pourquoi SQL n'a pas une syntaxe comme

SELECT tbl1.col1, tbl2.col2
  FROM tbl1
  JOIN tbl2 USING(FK_tbl1_tbl2)

où FK_tbl1_tbl2 est une contrainte de clé étrangère entre les tables. Ce serait incroyablement beaucoup plus utile que NATURAL JOIN ou Oracle (USING (col1, col2).

0
erikkallen

La raison principale est qu’il n’ya aucun moyen de les configurer sans interrogation dans la plupart des outils graphiques de MySQL (Navicat, MySQL, etc.).

Cela semble stupide mais je suis coupable de cela aussi car je n’ai pas la syntaxe mémorisée: /

0
Andrew G. Johnson