J'ai une table qui contient des données, et l'une de ces lignes doit exister dans une autre table. Donc, je veux une clé étrangère pour maintenir l'intégrité référentielle.
CREATE TABLE table1
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
AnotherID INT NOT NULL,
SomeData VARCHAR(100) NOT NULL
)
CREATE TABLE table2
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
AnotherID INT NOT NULL,
MoreData VARCHAR(30) NOT NULL,
CONSTRAINT fk_table2_table1 FOREIGN KEY (AnotherID) REFERENCES table1 (AnotherID)
)
Cependant, comme vous pouvez le voir, la table dans laquelle je clé étrangère, la colonne n'est pas le PK. Existe-t-il un moyen de créer cette clé étrangère, ou peut-être un meilleur moyen de maintenir cette intégrité référentielle?
sql
sql-server
Craig
la source
la source
table1.ID
?Réponses:
Si vous voulez vraiment créer une clé étrangère vers une clé non primaire, il DOIT être une colonne qui a une contrainte unique dessus.
À partir de Books Online :
Donc dans votre cas si vous faites
AnotherID
unique, cela sera autorisé. Si vous ne pouvez pas appliquer une contrainte unique, vous n'avez pas de chance, mais cela a vraiment du sens si vous y réfléchissez.Cependant, comme cela a été mentionné, si vous avez une clé primaire parfaitement bonne comme clé candidate, pourquoi ne pas l'utiliser?
la source
Comme d'autres l'ont souligné, idéalement, la clé étrangère serait créée en tant que référence à une clé primaire (généralement une colonne IDENTITY). Cependant, nous ne vivons pas dans un monde idéal, et parfois même une «petite» modification d'un schéma peut avoir des effets d'entraînement significatifs sur la logique de l'application.
Prenons le cas d'une table Customer avec une colonne SSN (et une clé primaire stupide) et une table Claim qui contient également une colonne SSN (remplie par la logique métier à partir des données Customer, mais aucun FK n'existe). La conception est imparfaite, mais elle est utilisée depuis plusieurs années et trois applications différentes ont été construites sur le schéma. Il devrait être évident que déchirer Claim.SSN et mettre en place une vraie relation PK-FK serait idéal, mais serait également une refonte importante . D'autre part, mettre une contrainte UNIQUE sur Customer.SSN, et ajouter un FK sur Claim.SSN, pourrait fournir une intégrité référentielle, avec peu ou pas d'impact sur les applications.
Ne vous méprenez pas, je suis tout à fait pour la normalisation, mais parfois le pragmatisme l'emporte sur l'idéalisme. Si une conception médiocre peut être aidée avec un pansement, la chirurgie peut être évitée.
la source
Nécromancie.
Je suppose que lorsque quelqu'un atterrit ici, il a besoin d'une clé étrangère pour colonne dans une table qui contient des clés non uniques.
Le problème est que si vous rencontrez ce problème, le schéma de base de données est dénormalisé.
Vous conservez par exemple des salles dans une table, avec une clé primaire room-uid, un champ DateFrom et DateTo, et un autre uid, ici RM_ApertureID pour garder une trace de la même room, et un champ soft-delete, comme RM_Status, où 99 signifie «supprimé» et <> 99 signifie «actif».
Ainsi, lorsque vous créez la première salle, vous insérez RM_UID et RM_ApertureID avec la même valeur que RM_UID. Ensuite, lorsque vous mettez fin à la salle à une date et que vous la rétablissez avec une nouvelle plage de dates, RM_UID est newid () et le RM_ApertureID de l'entrée précédente devient le nouveau RM_ApertureID.
Donc, si c'est le cas, RM_ApertureID est un champ non unique et vous ne pouvez donc pas définir de clé étrangère dans une autre table.
Et il n'y a aucun moyen de définir une clé étrangère sur une colonne / un index non unique, par exemple dans T_ZO_REM_AP_Raum_Reinigung (WHERE RM_UID est en fait RM_ApertureID).
Mais pour interdire les valeurs invalides, vous devez définir une clé étrangère, sinon, le gaspillage de données est le résultat le plus tôt possible ...
Maintenant, ce que vous pouvez faire dans ce cas (à moins de réécrire l'ensemble de l'application) est d'insérer une contrainte CHECK, avec une fonction scalaire vérifiant la présence de la clé:
la source
Les clés primaires doivent toujours être uniques, les clés étrangères doivent autoriser des valeurs non uniques si la table est une relation un-à-plusieurs. Il est parfaitement normal d'utiliser une clé étrangère comme clé primaire si la table est connectée par une relation un-à-un, et non une relation un-à-plusieurs.
Une contrainte FOREIGN KEY ne doit pas être liée uniquement à une contrainte PRIMARY KEY dans une autre table; il peut également être défini pour référencer les colonnes d'une contrainte UNIQUE dans une autre table.
la source