7
votes

Contrainte de clé étrangère bidirectionnelle

Je pense à concevoir un schéma de base de données similaire à ce qui suit:

Person (
  PersonID int primary key,
  PrimaryAddressID int not null,
  ...
)

Address (
  AddressID int primary key,
  PersonID int not null,
  ...
)


0 commentaires

6 Réponses :


0
votes

Le deuxième FK (Personnage de l'adresse à la personne) est trop restrictif, IMHO. Suggérez-vous qu'une seule adresse ne peut avoir qu'une seule personne?


3 commentaires

Oui, chaque adresse est spécifique à une personne. Je ne pense pas que cela ferait beaucoup de différence si je l'ai transformée en une relation plusieurs à plusieurs.


Voulez-vous jamais partager les enregistrements d'adresse? M. Person et Mme Person sont-ils partager la même adresse ou auraient-ils des enregistrements d'adresse distincts (mais identiques)?


Non, les enregistrements d'adresse ne seront jamais partagés.



0
votes

De votre conception, il semble que une adresse puisse s'appliquer à une seule personne, alors utilisez simplement la personne signalidée comme clé de la table d'adresses et déposez le champ KeydorSID.


5 commentaires

Chaque personne peut avoir plusieurs adresses.


Oui. C'était mon raisonnement pour mettre une colonne principaleDressid dans la table de la personne plutôt que d'avoir une colonne isprimée dans la table d'adresses.


Ensuite, vous devrez autoriser une valeur nulle dans votre domaine principaleDDRESSID et appliquer la règle d'entreprise de votre application plutôt que dans la DB - ou vous pourriez autoriser le champ Personnage dans le tableau d'adresses d'être null, puis remplissez-le plus tard - ou pourrait toucher la table d'adresses avec PersonID et Numéro d'adresses


Pouvez-vous expliquer "Vous pouvez enregistrer la table d'adresse avec PersonID et AdresseNumber"?


Ajoutez un nouveau champ AdresseNumber à la table et la touche - Thkey devient Personnier et Numéro d'adresse, remplaçant la clé d'adresses d'origine. La première adresse pour une personne obtient ensuite l'adresse de l'adresse 1, la seconde obtient l'adresse 2, etc. Les chiffres ne doivent pas nécessairement être séquentiels et il peut y avoir des lacunes lorsque des adresses sont supprimées. Je n'aime généralement pas généralement les clés principales de deux champs, alors je n'utiliserais probablement pas cette solution moi-même - je permettrais soit NULL dans le champ primaireDDRESSID afin que je puisse le remplir plus tard, ou utiliser une table à plusieurs à plusieurs. sinon suggéré.



2
votes

Nous marquons l'adresse principale dans notre tableau d'adresse, puis des déclencheurs qui appliquent uniquement l'enregistrement par personne ne peuvent l'avoir (mais un enregistrement doit l'avoir). Si vous modifiez l'adresse principale, elle mettra à jour l'ancienne adresse principale ainsi que la nouvelle. Si vous supprimez une adresse primaire et d'autres adresses existent, il faudra promouvoir l'un d'entre eux (BasesD ONA série de règles) à l'adresse primaire. Si l'adresse est insérée et que la première adresse est insérée, elle marquera celle-ci automatiquement en tant qu'adresse principale.


3 commentaires

C'est définitivement la conception que j'ai vue auparavant - sauf sans les déclencheurs et l'application de la loi dans la demande. Outre l'entretien supplémentaire, je ne suis pas sûr de la manière dont les déclencheurs fiables seraient. Êtes-vous sûr de couvrir tous les scénarios possibles?


Oui, je suis sûr que nos déclencheurs ont été testés très soigneusement et ont travaillé sans problème depuis des années. D'accord que l'utilisation de déclencheurs pour faire ceci est un processus complexe (mais cela le fait dans la demande et c'est un risque beaucoup plus élevé pour l'intégrité des données) et ils doivent être soigneusement testés (en particulier avec plusieurs inserts / mises à jour / mises à jour / Suppression). Les déclencheurs sont essentiels à notre système, car nous recevons des données de nombreuses applications et de nombreuses autres sources (nous faisons plusieurs centaines d'importations de données par semaine). Ce processus doit être sous forme de déclenchement si vous souhaitez assurer l'intégrité des données.


Une meilleure approche au lieu des déclencheurs constituerait une contrainte clé unique sur une colonne calculée "Uniquecolumn comme cas quand est-ce que l'isprima est alors personnalide d'autre fin de finale"



3
votes

C'est un exemple parfait de relation de plusieurs à plusieurs. Pour résoudre que vous devriez avoir une table intermédiaire Person_Address. En d'autres termes;

PERSON table
person_id (PK)

ADDRESS table
address_id (PK)

PERSON_ADDRESS
person_id (FK) <= PERSON
address_id (FK) <= ADDRESS
is_primary (BOOLEAN - Y/N)


2 commentaires

Je ne pense pas que cela résout le problème - cela l'évite simplement en relaxant la relation. Ceci semblable à lâcher la contrainte de clé étrangère sur l'adresse.personid


Ensuite, vous devriez faire respecter cette règle d'entreprise (chaque personne doit avoir une adresse primaire) par une gâchette sur la table de la personne. Le modèle que j'ai décrit devrait soutenir cette règle d'entreprise.



13
votes

"Je crois que c'est impossible. Vous ne pouvez pas créer d'enregistrement d'adresse tant que vous ne connaissez que l'ID de la personne et que vous ne pouvez pas insérer l'enregistrement de la personne avant de connaître un adressé pour le champ primaireAddRESID."

sur la face de celui-ci, cette revendication semble si attrayante. Cependant, c'est assez proposant.

C'est un type de problème très courant que les fournisseurs SQL DBMS tentent d'attaquer pour peut-être des décennies déjà.

La clé est que toutes les vérifications de contrainte doivent être "différées" jusqu'à ce que les deux inserts soient terminés. Cela peut être atteint sous différentes formes. Les transactions de base de données peuvent offrir la possibilité de faire quelque chose comme "Définir la vérification de la contrainte différée sur" et que vous avez terminé (n'était-ce pas pour le fait que dans cet exemple particulier, vous devriez probablement jouer très fort avec votre conception afin Pour pouvoir simplement définir les deux contraintes FK, parce que l'une d'entre elles n'est tout simplement pas une «vraie» FK dans le sens SQL!).

Des solutions basées sur la gâchette telles que décrites ici atteignent essentiellement le même effet, mais celles-ci sont exposées à tous les problèmes de maintenance existants avec intégrité appliquée.

Dans leur travail, Chris Date & Hugh Darwen décrit ce qui est imo la vraie solution au problème: mission multiple. C'est essentiellement la possibilité de composer plusieurs relevés de mise à jour distincts et de faire agir le SGBD comme s'il s'agissait d'une seule déclaration. Des implémentations de ce concept existent, mais vous ne trouverez aucun qui parle SQL.


1 commentaires

Cette réponse a rempli un écart dans mes connaissances sur le fonctionnement de SQL.



-1
votes

Je sais que je serai probablement crucifié ou quoi que ce soit, mais voilà ...

Je l'ai fait comme ça pour mon besoin d'entreprise "particulièrement propre unique et non standard" (= (dieu I ' m commençant à sonner comme SQL DDL, même lorsque je parle). P>

Voici un exaxmple: P>

CREATE TABLE IF NOT EXISTS PERSON(
    ID INT, 
    CONSTRAINT PRIMARY KEY (ID), 
    ADDRESS_ID INT NOT NULL DEFAULT 1, 
    DESCRIPTION VARCHAR(255), 
    CONSTRAINT PERSON_UQ UNIQUE KEY (ADDRESS_ID, ...));

INSERT INTO PERSON(ID, DESCRIPTION) 
    VALUES (1, 'GOVERNMENT');

CREATE TABLE IF NOT EXISTS ADDRESS(
    ID INT, 
    CONSTRAINT PRIMARY KEY (ID), 
    PERSON_ID INT NOT NULL DEFAULT 1, 
    DESCRIPTION VARCHAR(255), 
    CONSTRAINT ADDRESS_UQ UNIQUE KEY (PERSON_ID, ...), 
    CONSTRAINT ADDRESS_PERSON_FK FOREIGN KEY (PERSON_ID) REFERENCES PERSON(ID));

INSERT INTO ADDRESS(ID, DESCRIPTION) 
    VALUES (1, 'ABANDONED HOUSE AT THIS ADDRESS');

ALTER TABLE PERSON ADD CONSTRAINT PERSON_ADDRESS_FK FOREIGN KEY (ADDRESS_ID) REFERENCES ADDRESS(ID);


1 commentaires

La solution standard à cette est à utiliser des contraintes différées (comme étant erwin mentionné). Cependant, tous les SGDM ne sont pas suffisamment avancés pour soutenir cela.