2009-03-21 6 views
81

Je dois deux tables à savoir employees_ce et employees_sn sous les employés de la base de données.Clé étrangère faisant référence à des clés primaires sur plusieurs tables?

Ils ont tous les deux leur colonne de clé primaire unique respective.

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

par exemple

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

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

est donc ce possible?

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

Répondre

2

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 pas pourquoi vous avez deux tables. Aucune relation à plusieurs. Et (pas dans cet exemple) beaucoup de colonnes.

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

1

Oui, c'est possible. Vous devrez définir 2 FK pour la 3ème table. Chaque FK pointant vers le (s) champ (s) requis d'une table (c.-à-d. 1 FK par table étrangère).

21

Vous pouvez probablement ajouter deux contraintes de clé étrangère (honnêtement: je ne l'ai jamais essayé), mais il insistera alors pour que la ligne parent existe dans les deux tables. A la place, vous voudrez probablement créer un supertype pour vos deux sous-types d'employés, puis pointez la clé étrangère à la place. (En supposant que vous avez une bonne raison de diviser 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 ou sn.

+0

J'ai essayé d'ajouter plusieurs clés étrangères, ils travaillaient, mais, tout en ajoutant un record, derby java me dit les clés étrangères ont été violés! –

+0

Je viens de l'essayer sur PostgreSQL, et ça marche là-bas. Aviez-vous l'enregistrement parent dans les deux tableaux? – derobert

+0

parent enregistrement que vous voulez dire, le empid? –

87

En supposant que je comprends bien votre scénario, ce que je qualifierais le droit façon de le faire:

Début d'une description plus 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 niveau supérieur à trois tables: employees, employees_ce et employees_sn:

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

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

Pour désigner un employé de toute sorte (ce ou sn), reportez-vous au tableau employees. Autrement dit, la clé étrangère avec laquelle vous avez eu des problèmes devrait se référer à cette table!

+12

Comment faites-vous ce et sn mutuellement exclusifs? Puisqu'un employé ne peut pas être en même temps ce et sn, il serait bon de le refléter dans la base de données. J'ai ce problème en ce moment. – Rolf

+0

Je pense que plusieurs clés de colonne pourraient aider avec le problème dans mon commentaire précédent ... en levant cette question maintenant. – Rolf

+12

Vous pouvez forcer l'employé à être dans une seule table (et la bonne) en stockant un type dans la table de base ainsi que les tables dérivées. Créez l'ID de clé primaire, une clé unique sur (id, type), la clé étrangère des tables enfant sur (id, type) et placez une contrainte CHECK sur chaque table enfant pour avoir uniquement le bon type. Ou, si votre base de données vérifie les contraintes globales (et sans pénalité de vitesse énorme), vous pouvez bien sûr faire une vérification NOT EXISTS. – derobert

0

En supposant que vous devez avoir deux tables pour les deux types d'employés pour une raison quelconque, je transmets sur la réponse vmarquez:

Schéma:

employees_ce (id, name) 
employees_sn (id, name) 
deductions (id, parentId, parentType, name) 

données dans les déductions:

deductions table 
id  parentId  parentType  name 
1  1    ce    gold 
2  1    sn    silver 
3  2    sn    wood 
... 

Cela vous permettrait d'avoir des déductions pointent vers n'importe quelle autre table dans votre schéma. Ce type de relation n'est pas supporté par les contraintes au niveau de la base de données, IIRC, vous devrez donc vous assurer que votre application gère correctement la contrainte (ce qui la rend plus encombrante si plusieurs applications/services touchent la même base de données).

15

En fait, je le fais moi-même. J'ai une table appelée "Commentaires" qui contient des commentaires pour les enregistrements dans 3 autres tables. Aucune solution ne gère réellement tout ce que vous voulez probablement. 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érent dans chaque tableau (Ce champ représente un ' Identificateur de table ', donc nous les appellerons tid_ce tid_sn)

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

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

  4. Créer 2 clés étrangères dans votre table « déductions » (Vous ne pouvez pas appliquer l'intégrité référentielle, parce que l'une clé sera valide ou 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 l'intégrité référentielle être ma intained: 1. Créez un deuxième champ de clé étrangère dans la table «déductions, permettent des valeurs nulles 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   

intégrité est vérifiée uniquement si la colonne est non nul, donc vous pouvez maintenir l'intégrité référentielle.

6

Je sais que ce sujet est stagnant depuis longtemps, mais dans le cas où quelqu'un cherche ici, c'est la façon dont je traite les clés étrangères multi-tables. Avec cette technique, vous n'avez aucune opération en cascade DBA, alors assurez-vous de traiter avec DELETE et ainsi de suite 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) 

SO l'exemple Op ressemblerait à ceci

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

types 
--------------------- 
1 employees_ce 
2 employees_sn 
Questions connexes