3
votes

Puis-je avoir une colonne pour deux valeurs différentes avec une clé étrangère de deux tables différentes?

J'ai donc cette table Addresses

CREATE TABLE Addresses
(
Address_ID VARCHAR (10) PRIMARY KEY,
Student_ID/Staff_Number VARCHAR (20),
Name CHAR (50),
Surname CHAR (30),
Building/House_Number INT (5),
Street CHAR (20),
City CHAR (30),
Postcode VARCHAR (10)
FOREIGN KEY (Student_ID) REFERENCES Students (Student_ID)
);

Le truc est la ligne Student_ID / Staff_Number VARCHAR (20), est soit provenant de la table des étudiants ou de la table du personnel. Puis-je attribuer deux clés étrangères?


4 commentaires

«Plusieurs valeurs liées à différentes tables dans une seule colonne sont le chemin vers le côté obscur… Plusieurs valeurs liées à différentes tables dans une seule colonne mènent à la colère… la colère conduit à la haine… la haine conduit à la souffrance» - Chaque DBA Ever


Mauvaise direction. Mettez addressid dans la table des étudiants avec un fk, et dans la table des professeurs aussi.


@jarlh Pensez également à avoir des tables student_address et staff_address afin de sauvegarder plusieurs adresses ( home , work , etc. ) par type d'utilisateur.


@jarlh Complètement d'accord. J'ai donné quelques options dans ma réponse, et c'était ma recommandation personnelle. :-)


3 Réponses :


0
votes

Non, ce n'est pas possible.

Vous envisagez probablement d'implémenter une sorte de modèle d'héritage dans votre conception où vous avez quelque chose comme une table de base 'person' que les tables des étudiants et des professeurs étendent et la clé étrangère pointe vers cela à la place.

P.S. Vos colonnes varchar Ids sont-elles les index clusterisés? Cela peut nuire aux performances, pensez à une colonne d'identité de substitution pour le clustering


0 commentaires

-1
votes

Vous pouvez toujours ajouter plusieurs contraintes de clé étrangère sur une seule colonne, mais TOUTES d'entre elles seront appliquées, pas seulement l'une d'entre elles. Par exemple:

CREATE TABLE Addresses
(
Address_ID VARCHAR (10) PRIMARY KEY,
Student_ID VARCHAR (20),
Staff_ID VARCHAR(20),
Name CHAR (50),
Surname CHAR (30),
Building/House_Number INT (5),
Street CHAR (20),
City CHAR (30),
Postcode VARCHAR (10),
FOREIGN KEY (Student_ID) REFERENCES Students (Student_ID),
FOREIGN KEY (Staff_ID) REFERENCES Staff (Staff_ID),
constraint ct1 check (Student_ID is null and Staff_ID is not null
                   or Student_ID is not null and Staff_ID is null)
);

Ce n'est probablement pas ce que vous voulez. Ce que vous voulez probablement, c'est avoir deux colonnes, chacune pointant vers une table distincte; et pour ceux aux colonnes, l'un est toujours nul et l'autre n'est pas nul. Vous pouvez le faire comme indiqué ci-dessous:

CREATE TABLE Addresses
(
Address_ID VARCHAR (10) PRIMARY KEY,
Student_ID VARCHAR (20),
Name CHAR (50),
Surname CHAR (30),
Building/House_Number INT (5),
Street CHAR (20),
City CHAR (30),
Postcode VARCHAR (10),
FOREIGN KEY (Student_ID) REFERENCES Students (Student_ID)
FOREIGN KEY (Student_ID) REFERENCES Staff (Staff_ID)
);

La contrainte ct1 garantit qu’un et un seul d’entre eux est "actif" à un moment donné de heure.


0 commentaires

1
votes

D'accord, c'est moins un "comment faire une chose spécifique X?" et plus encore "Comment devrais-je faire cela?"

Parce que, pour être honnête, vous ne voulez pas le faire comme vous essayez de le mettre en page.

Permettez-moi de vous donner quelques alternatives qui sont meilleures du point de vue de la disposition de la base de données:

  1. Inversez la relation (ma recommandation). Au lieu de la table d'adresses liée au personnel / étudiant, demandez au personnel / étudiant lié à un AddressID.
  2. Consolider les deux tableaux dans un tableau de personne (un autre très bon choix). De cette façon, vous n'avez qu'une seule table à laquelle la table d'adresses est liée. Ensuite, si certains champs sont applicables à un seul type de personne (personnel uniquement, étudiant uniquement, etc.) - déchargez uniquement ces colonnes dans une table dédiée pour celles-ci uniquement des champs. Vous pouvez donc avoir une table Person avec toutes les informations de base, une table Address qui renvoie à la table Person, une table Student avec une colonne GradeLevel et une table Staff avec une colonne SubjectTaught.
  3. Vous disposez de deux tableaux d'adresses distincts: un pour les étudiants et un pour le personnel. Vous souhaitez créer un lien vers le tableau des étudiants? Génial - vous a obtenu le StudentID dans la table StudentAddress. Et la même chose avec le personnel.
  4. Avoir une colonne indiquant le type de destinataire. 0 pour les étudiants, 1 pour le personnel. Ne mettez pas du tout la contrainte de clé étrangère.
  5. Ayez deux colonnes distinctes - une pour l'ID étudiant, une pour l'ID du personnel (probablement, l'une sera toujours nulle.) clé étrangère à la table respective (les clés étrangères peuvent avoir null valeurs.)

... tout cela sonne mieux que d'essayer de créer une clé étrangère partagée. Pire encore, que se passe-t-il si un étudiant et un membre du personnel partagent une pièce d'identité? À quelle entité cette adresse s'applique-t-elle?


4 commentaires

Ou ayez une table commune pour le personnel et les étudiants. (Certains élèves des écoles supérieures enseignent aussi.)


@jarlh - bon point. Je pense que je vais développer un peu cela et l'ajouter à la liste


Merci d'avoir répondu! Pour vous assurer qu'ils ont des identifiants uniques. Je dois avoir deux tables différentes pour les étudiants et le personnel, alors je vais utiliser deux tables différentes pour les adresses, je suppose. Est-ce que cela complique les choses car j'essaie de le faire de la manière la plus simple possible?


Honnêtement, le plus simple consiste simplement à inverser la relation entre les tables. Au lieu de faire pointer l'adresse vers les tables Student / Staff, faites simplement pointer les tables Student / Staff vers la table Address. Avoir un identifiant AddressID dans votre table d'adresses et les deux autres tables ont une colonne AddressID qui pointe vers elle.