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é.
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.
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.
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 KEY
s 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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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).
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: /