Est-il acceptable d'avoir une référence circulaire entre deux tables sur le champ de clé étrangère?
Sinon, comment éviter ces situations?
Si oui, comment insérer des données?
Voici un exemple où (à mon avis) une référence circulaire serait acceptable:
CREATE TABLE Account
(
ID INT PRIMARY KEY IDENTITY,
Name VARCHAR(50)
)
CREATE TABLE Contact
(
ID INT PRIMARY KEY IDENTITY,
Name VARCHAR(50),
AccountID INT FOREIGN KEY REFERENCES Account(ID)
)
ALTER TABLE Account ADD PrimaryContactID INT FOREIGN KEY REFERENCES Contact(ID)
database-design
foreign-key
rdbms
KidCode
la source
la source
Réponses:
Puisque vous utilisez des champs nullables pour les clés étrangères, vous pouvez en fait construire un système qui fonctionne correctement comme vous l'imaginez. Afin d'insérer des lignes dans la table des comptes, vous devez avoir une ligne présente dans la table des contacts, sauf si vous autorisez les insertions dans les comptes avec un PrimaryContactID nul. Afin de créer une ligne de contact sans avoir déjà une ligne de compte présente, vous devez autoriser la colonne AccountID dans la table Contacts pour être nullable. Cela permet aux comptes de ne pas avoir de contacts et aux contacts de ne pas avoir de compte. C'est peut-être souhaitable, peut-être pas.
Cela dit, ma préférence personnelle serait d'avoir la configuration suivante:
Cela permet de:
IX_AccountsContactsXRef_Primary
index. Cet index contient un filtre, il ne fonctionnera donc que sur les plates-formes qui les prennent en charge. Étant donné que cet index est spécifié avec l'UNIQUE
option, il ne peut y avoir qu'un seul contact principal pour chaque compte.Par exemple, si vous souhaitez afficher une liste de tous les contacts, avec une colonne indiquant le statut "principal", montrant les contacts principaux en haut de la liste pour chaque compte, vous pouvez faire:
L'index filtré empêche l'insertion de plus d'un seul contact principal par compte, tout en fournissant simultanément une méthode rapide de renvoi d'une liste de contacts principaux. On pourrait facilement imaginer une autre colonne,
IsActive
avec un index filtré non unique pour conserver un historique des contacts par compte, même après que ce contact ne soit plus associé au compte:la source
Non, il n'est pas acceptable d'avoir des références de clés étrangères circulaires. Non seulement parce qu'il serait impossible d'insérer des données sans supprimer et recréer constamment la contrainte. mais parce que c'est un modèle fondamentalement imparfait de tous les domaines auxquels je peux penser. Dans votre exemple, je ne peux penser à aucun domaine dans lequel la relation entre le compte et le contact n'est pas NN, nécessitant une table de jonction avec des références FK vers le compte et le contact.
la source
Vous pouvez faire pointer votre objet externe vers le contact principal plutôt que vers le compte. Vos données ressembleraient à ceci:
la source