96 votes

Clé étrangère se référant à des clés primaires sur plusieurs tables ?

J'ai deux tables, employees_ce et employees_sn, dans la base de données employees.

Ils ont tous deux leurs colonnes de clé primaire uniques respectives.

J'ai une autre table appelée déductions, dont je veux référencer la colonne de clé étrangère aux clés primaires de employees_ce ainsi que de employees_sn. Est-ce possible ?

par exemple

employees_ce
--------------
empid   name
khce1   prince

employees_sn
----------------
empid   name
khsn1   princess

Est-ce possible ?

deductions
--------------
id      name
khce1   gold
khsn1   silver

107voto

En supposant que j'ai bien compris votre scénario, c'est ce que j'appellerais la droite manière de le faire :

Commencez par une description de haut niveau de votre base de données ! Vous avez des employés, et les employés peuvent être des employés "ce" et des employés "sn" (quels qu'ils soient). En termes orientés objet, il existe une classe "employee", avec deux sous-classes appelées "ce employee" et "sn employee".

Ensuite, vous traduisez cette description de haut niveau en trois tableaux : employees , employees_ce y employees_sn :

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

Puisque tous les employés sont des employés (duh !), chaque employé aura une ligne dans le fichier employees table. Les employés "ce" ont également une rangée dans la table employees_ce et les employés "sn" ont également une ligne dans la table employees_sn table. employees_ce.id est une clé étrangère à employees.id tout comme employees_sn.id est.

Pour désigner un employé de quelque nature que ce soit (ce ou sn), il faut se référer à la rubrique employees table. En d'autres termes, la clé étrangère avec laquelle vous avez eu des problèmes doit faire référence à cette table !

23voto

derobert Points 26258

Vous pouvez probablement ajouter deux contraintes de clé étrangère (honnêtement : je ne l'ai jamais essayé), mais il faudrait alors insister pour que la ligne parent existe dans les deux tables.

Au lieu de cela, vous voudrez probablement créer un super-type pour vos deux sous-types d'employés, puis y faire pointer la clé étrangère. (En supposant que vous ayez une bonne raison de séparer les deux types d'employés, bien sûr).

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————> empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name

type dans la table des employés serait ce o sn .

21voto

LittleC Points 61

En fait, je le fais moi-même. J'ai une table appelée "Commentaires" qui contient les commentaires des enregistrements de trois autres tables. Aucune des deux solutions ne permet de gérer tout ce que vous souhaitez. Dans votre cas, vous feriez ceci :

Solution 1 :

  1. Ajouter un champ tinyint à employees_ce et employees_sn qui a une valeur par défaut qui est différente dans chaque table (Ce champ représente un 'identifiant de table', donc nous les appellerons tid_ce & tid_sn)

  2. Créez un index unique sur chaque table en utilisant le PK de la table et le champ id de la table.

  3. Ajoutez un champ tinyint à votre table 'Deductions' pour stocker la seconde moitié de la clé étrangère (l'ID de la table).

  4. Créez 2 clés étrangères dans votre table 'Deductions' (Vous ne pouvez pas appliquer l'intégrité référentielle, parce que soit une clé sera valide, soit l'autre... mais jamais les deux :

    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_ce] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce]
    GO
    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_sn] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn]
    GO
    
    employees_ce
    --------------
    empid    name     tid
    khce1   prince    1
    
    employees_sn
    ----------------
    empid    name     tid 
    khsn1   princess  2
    
    deductions
    ----------------------
    id      tid       name  
    khce1   1         gold
    khsn1   2         silver         
    ** id + tid creates a unique index **

Solution 2 : Cette solution permet de maintenir l'intégrité référentielle : 1. Créer un deuxième champ de clé étrangère dans la table 'Deductions', autoriser les valeurs Null dans les deux clés étrangères, et créer des clés étrangères normales :

    employees_ce
    --------------
    empid   name
    khce1   prince 

    employees_sn
    ----------------
    empid   name     
    khsn1   princess 

    deductions
    ----------------------
    idce    idsn      name  
    khce1   *NULL*    gold
    *NULL*  khsn1     silver         

L'intégrité n'est vérifiée que si la colonne n'est pas nulle, ce qui vous permet de maintenir l'intégrité référentielle.

6voto

Brian Sallee Points 81

Je sais que c'est un sujet qui stagne depuis longtemps, mais au cas où quelqu'un chercherait, voici comment je gère les clés étrangères de plusieurs tables. Avec cette technique, il n'y a pas d'opérations en cascade imposées par le DBA, donc assurez-vous de traiter les cas suivants DELETE et autres dans votre code.

Table 1 Fruit
pk_fruitid, name
1, apple
2, pear

Table 2 Meat
Pk_meatid, name
1, beef
2, chicken

Table 3 Entity's
PK_entityid, anme
1, fruit
2, meat
3, desert

Table 4 Basket (Table using fk_s)
PK_basketid, fk_entityid, pseudo_entityrow
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table)
2, 1, 1 (Apple)
3, 1, 2 (pear)
4, 3, 1 (cheesecake)

L'exemple de SO Op ressemblerait à ceci

deductions
--------------
type    id      name
1      khce1   gold
2      khsn1   silver

types
---------------------
1 employees_ce
2 employees_sn

2voto

Sascha Points 6482

Techniquement possible. Vous feriez probablement référence à employees_ce dans les déductions et employees_sn. Mais pourquoi ne pas fusionner employees_sn et employees_ce ? Je ne vois aucune raison pour laquelle vous avez deux tables. Il n'y a pas de relation un à plusieurs. Et (pas dans cet exemple) plusieurs colonnes.

Si vous faites deux références pour une colonne, un employé doit ont une entrée dans les deux tableaux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X