2009-04-02 6 views
1

J'essaie de déterminer s'il est possible de créer une clé étrangère de cette manière.Question de clé étrangère composite

Il existe d'abord deux tables parent dans ce scénario.

Le Tableau 1 a un PK int et une autre colonne int. Une fois combinés, les deux sont uniques.

Le tableau 2 a un PK int et une autre colonne int. Une fois combinés, les deux sont uniques.

La valeur appariée entre les deux entrées est la façon dont nous sélectionnons actuellement les enregistrements enfants pour l'une ou l'autre table.

Le tableau 3 a une valeur pour la colonne PK et autre int de l'une des deux premières tables. Il est sélectionnable de manière fiable parce que les deux champs utilisés dans une recherche sont uniques à l'un des tableaux ci-dessus. Je cherche donc à créer un FK ou éventuellement deux FK pour ce scénario. J'aimerais pouvoir faire des suppressions en cascade de l'une ou l'autre des premières tables dans la troisième table, et j'aimerais également l'utiliser pour les relations d'entité dans Entity Framework.

S'il vous plaît laissez-moi savoir si cela n'a pas de sens. Je l'ai lu plusieurs fois, et c'est aussi clair que possible.

Merci

Répondre

0

Si Table3 contient toutes les valeurs dans le tableau 1 UNION Tableau 2, alors vous avez un inheritance scheme:

Table3 { (int id, int type) PK } 
Table1 { (int id, int type [CHECK type = 1]) FK Table3 } 
Table2 { (int id, int type [CHECK type = 2]) FK Table3 } 

Avec cela, la suppression de Table3 cascadera à ou Tableau 1 Tableau 2 de façon appropriée.

Sinon, si Table3 est juste un sous-ensemble de Table1 UNION Table2 - alors l'introduction de Table4 en tant qu'ensemble complet fonctionnerait.

Table4 { (int id, int type [CHECK type IN (1,2)]) PK } 
Table1 { (int id, int type [CHECK type = 1]) FK Table4 } 
Table2 { (int id, int type [CHECK type = 2]) FK Table4 } 
Table3 { (int id, int type) FK Table4 } 

Pour gérer les suppressions en cascade, cependant, vous aurez besoin de supprimer de Table4 (bien que vous pourriez faire un déclencheur sur Table3 pour gérer que pour vous).

Edit (parce que je pense qu'il est un point important qui devrait être vu, séparé des commentaires):

Oui, le problème est que l'un et deux sont les parents. Ils ont tous les deux des enregistrements liés dans 3, ce qui serait un FK, pas un PK pour cette table. Il semble être pratiquement impossible d'utiliser une contrainte FK. Merci pour la réponse! - Chrisb (il ya une heure)

IMO - votre modèle de données est alors brisé. Table1 et Table2 ne sont pas liés, mais vous essayez de les placer dans la même colonne que dans Table3. Si Table1 et Table2 sont liés d'une manière ou d'une autre, vous devez modéliser cela. Soit introduire une table parente (Table4) si elles sont liées, soit une deuxième colonne dans Table3 (Table1 FK, Table2 FK) ou 2 tables jointes si elles ne le sont pas. N'essayez pas de mettre une cheville ronde dans un trou carré - et n'essayez pas de compenser avec une gâchette. ;)

+0

Oui, le problème avec ceci est que un et deux sont les parents. Ils ont tous les deux des enregistrements liés dans 3, ce qui serait un FK, pas un PK pour cette table. Il semble être pratiquement impossible d'utiliser une contrainte FK. Merci pour la réponse! – Chrisb

+0

IMO - votre modèle de données est alors brisé. Table1 et Table2 ne sont pas liés, mais vous essayez de les placer dans la même colonne que dans Table3. Si Table1 et Table2 sont liées d'une manière ou d'une autre, Table4 doit être la table parente. –

+0

Je suis complètement d'accord, mais je n'ai aucun contrôle sur cela. Merci pour les commentaires, ils vérifient ce que je pensais complètement. – Chrisb

1

Si je vous comprends bien, vous avez 3 tables structurées comme suit:

TABLE_A: 
    PK_FIELD int NOT NULL 
    OTHER_FIELD int NOT NULL, NOT IN TABLE_B.OTHER_FIELD 

TABLE_B: 
    PK_FIELD int NOT NULL 
    OTHER_FIELD int NOT NULL, NOT IN TABLE_A.OTHER_FIELD 

TABLE_C: 
    PK_FIELD int NOT NULL 
    OTHER_FIELD int NOT NULL IN (TABLE_A.OTHER_FIELD OR TABLE_B.OTHER_FIELD 

Qu'est-ce que vous essayez de faire est de définir TABLE_C telle que vous pourriez en cascade des mises à jour et supprime entre les tables . En raison de la façon dont TABLE_A.OTHER_FIELD et TABLE_B.OTHER_FIELD sont définis, vous garantissez qu'il n'y a pas de chevauchement entre eux. Le problème consiste à déterminer quelle table a la référence à TABLE_C. Ce que vous pouvez faire avec cette définition est cascade de TABLE_A ou TABLE_B à TABLE_C puisque la relation est assez claire dans cette direction. Cependant, cascade de TABLE_C vers le haut est plus compliqué, puisque vous ne savez pas quelle table à cascade. Soit définir deux champs dans TABLE_C un pour référencer chacune des autres tables, puis vous pouvez définir la relation entre les trois tables, sachant que pour un enregistrement donné, il n'y aura qu'une ou deux tables impliquées, jamais les trois. Vous pouvez également utiliser le code pour déterminer quelle table associer cette ligne particulière et cascader en conséquence.

+0

Oui, c'est exactement ça. Je ne me soucie pas d'aller de la table 3 sauvegarder cependant. Connaissez-vous le type de code T-SQL dont j'ai besoin pour créer les contraintes du tableau 3? – Chrisb

+0

Je ne suis pas sûr s'il existe un moyen de définir une contrainte formelle qui vous donnerait ceci avec une seule colonne. Si vous utilisez la solution à deux colonnes, chaque champ est nullable, et il existe une contrainte de table qui indique exactement l'un des deux champs est null. – Elie

0

Je ne sais pas quels dbms vous utilisez mais je ne connais pas ceux qui acceptent les multi-parents. Ce que vous pouvez faire est de définir un index sur table3 (juste pour être plus rapide) et implémenter la suppression en cascade dans votre application.

+0

J'utilise SQL Server 2005. – Chrisb

Questions connexes