Question

Je songe à concevoir un schéma de base de données similaire à celui-ci:

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

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

Person.PrimaryAddressID et Address.PersonID seraient des clés étrangères des tables correspondantes.

Le problème évident est qu’il est impossible d’insérer quoi que ce soit dans l’un ou l’autre tableau. Existe-t-il un moyen de concevoir un schéma fonctionnel qui applique chaque personne ayant une adresse principale?

Était-ce utile?

La solution

& "Je pense que c'est impossible. Vous ne pouvez pas créer un enregistrement d'adresse tant que vous ne connaissez pas l'ID de la personne et que vous ne pouvez pas l'insérer tant que vous ne connaissez pas AddressId pour le champ PrimaryAddressId. & Quot;

À première vue, cette affirmation semble si attrayante. Cependant, il est assez proposeux.

Il s'agit d'un type de problème très courant que les fournisseurs de SGBD SQL tentent d'attaquer depuis peut-être des décennies.

La clé est que toute vérification de contrainte doit être & "différée &"; jusqu'à ce que les deux inserts soient terminés. Cela peut être réalisé sous différentes formes. Les transactions de base de données peuvent offrir la possibilité de faire quelque chose comme & "; SET contrainte différée vérifiant ON &"; Et vous avez terminé (sans le fait que dans cet exemple particulier, vous auriez probablement vous bousiller très fort avec votre conception afin de pouvoir simplement définir les deux contraintes FK, car l’une d’elles n’est tout simplement pas un 'vrai' FK au sens SQL!).

Les solutions basées sur des déclencheurs, telles que décrites ici, produisent essentiellement le même effet, mais elles sont exposées à tous les problèmes de maintenance liés à l’intégrité imposée par les applications.

Dans leur travail, Chris Date & amp; Hugh Darwen décrit quelle est la vraie solution au problème: affectations multiples. C'est essentiellement la possibilité de composer plusieurs instructions de mise à jour distinctes et de laisser le SGBD agir dessus comme s'il s'agissait d'une seule instruction. Des implémentations de ce concept existent, mais vous n'en trouverez pas qui parle SQL.

Autres conseils

Nous marquons l’adresse principale dans notre table d’adresses, puis les déclencheurs n’appliquent qu’un enregistrement par personne (mais un enregistrement doit l’avoir). Si vous modifiez l'adresse principale, l'ancienne adresse principale et la nouvelle seront mises à jour. Si vous supprimez une adresse principale et que d’autres adresses existent, l’une d’elles (base d’une série de règles) sera promue en adresse principale. Si l'adresse est insérée et qu'il s'agit de la première adresse insérée, elle sera automatiquement marquée comme adresse principale.

Ceci est un exemple parfait de relation plusieurs à plusieurs. Pour résoudre ce problème, vous devez avoir une table PERSON_ADDRESS intermédiaire. 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)

De cette façon, vous pouvez attribuer plusieurs adresses à une PERSON et également réutiliser des enregistrements ADDRESS dans plusieurs PERSON (membres de la famille, employés de la même entreprise, etc.). En utilisant le champ is_primary de la table PERSON_ADDRESS, vous pouvez déterminer si cette combinaison person_addrees est une adresse principale pour une personne.

Le deuxième FK (PersonId de Address to Person) est trop restrictif, à mon humble avis. Êtes-vous en train de suggérer qu'une adresse ne peut avoir qu'une seule personne?

D'après votre conception, il semble qu'une adresse ne puisse s'appliquer qu'à une seule personne. Il vous suffit donc d'utiliser l'identifiant personnel comme clé de la table d'adresses et de supprimer le champ de clé AddressID.

Je sais que je serai probablement crucifié ou peu importe, mais voilà ...

Je l'ai fait comme ça pour mon & "particulier très unique, unique et non standard &"; besoin commercial (= (mon Dieu, je commence à ressembler à SQL DDL même quand je parle).

Voici un exemple:

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);

< ... la vie continue ... que vous fournissiez une adresse ou non à la personne et vice versa >

J'ai défini une table, puis l'autre table référençant la première, puis j'ai modifié la première pour refléter la référence à la seconde (qui n'existait pas au moment de la création de la première table). Ce n'est pas destiné à une base de données particulière; si j'en ai besoin, je l'essaie et si cela fonctionne, je l'utilise, sinon j'essaie d'éviter d'avoir ce besoin dans la conception (je ne peux pas toujours contrôler cela, parfois, la conception me est remise telle quelle). . si vous avez une adresse sans personne, elle appartient au "ient gouvernement " la personne. Si vous avez un & Quot; personne sans abri & Quot; alors il obtient la " maison abandonnée " adresse. Je lance un processus pour déterminer quelles maisons n'ont pas d'utilisateurs

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top