2014-11-25 47 views
0

请检查下面的表格对我的问题的一个简化版本:字段引用两个表 - 外键冲突

表男孩

BoyId 
BoyName 
... 

表女孩

GirlId 
GirlName 

桌上玩具

ToyId 
ToyName 
ToyOwnerBoyOrGirl (The toy could be owned by a boy or a girl) 
ToyOwnerId 

我创建了两个约束:

1)ToyOwnerId是主键Boys.BoyId

2)ToyOwnerId一个外键的主键Girls.GirlId

我的目的外键是告诉数据库,ToyOwnerId将永远是这些ID中的一个

我的问题: 当我尝试插入一个带有男孩ID的新玩具时,我得到了一个错误,在Girls约束中有一个foreign key conflict

这是一个包的设计,或者我仍然可以使用相同的设计与修复?

+0

您不能创建引用两个表的外键,没有数据库允许这样做。你将不得不改变你的模式(你说过你不能/不会),或者没有参考而生活。还要注意,如果你问“这是一个糟糕的设计”,而当答案是“是的,这是糟糕的设计”你的回答是“好的,但我不能改变它”,那么也许你不问正确的问题。 – 2014-11-25 14:51:37

+0

我还没说过我根本不能改变模式。我只在我的评论中提到,对两个实体使用单个表是不可能的。 – user3340627 2014-11-25 14:57:06

回答

1

它看起来像一个糟糕的设计。为什么没有一张桌子给所有的孩子和一些印记 - 是男孩还是女孩?此外,我真的怀疑你需要ToyOwnerBoyOrGirl的领域 - 因为它可以很容易地从玩具加入到业主。

考虑以下方案:

Table Children 
ID 
Name 
Is_Boy 

Table Toys 
ID 
Name 
Owner_ID 

在这种情况下,你需要从玩具到业主只是外键,和其他任务时可能会遇到将更加simplier解决。

编辑:根据OP的评论 - 男孩和女孩表是完全不同的。

因此,在这种情况下,您仍然可以将表Children(让我们使用以前的术语)作为BoysGirls的“公共”表。

喜欢的东西:

Table Children 

ID 
Table_Name ('Boys' or 'Girls' here) 
Record_ID (ID from Boys or Girls respectively) 
...maybe some common fields from boys and girls tables here... 


Table Boys 
ID 
Child_ID 
...the rest of fields 

Table Girls 
ID 
Child_ID 
...the rest of fields 
+0

是的,但每个表都有一组完全不同的字段,一个字段最多有80个字段,另一个字段只有10个字段。请注意男孩和女孩表只是我的实际表名称的同义词,它更复杂 – user3340627 2014-11-25 14:45:06

+0

查看更新的答案 – 2014-11-25 14:50:28

2

我想你应该在男孩和女孩的表结合起来,一个表中调用的孩子。它会有性别栏,将有一个M或F.这将简化的事情。

+0

我无法做到这一点,因为每个表都有一组完全不同的字段。我刚才在这里提到了简化的常用字段名称。 – user3340627 2014-11-25 14:45:51

+1

如果您隐瞒事实,然后要求我们对设计进行批评,您的结果将不尽如人意。 – 2014-11-25 14:48:16

2

你应该简单地在你的玩具表中加上两个ID加上检查约束,以确保总是男孩或女孩是所有者。

表玩具

  • ToyId
  • ToyName
  • ToyOwnerBoyId
  • ToyOwnerGirlId
 
    CONSTRAINT chkToyOwner CHECK 
    (
    (ToyOwnerBoyId is null and ToyOwnerGirlId is not null) 
    OR 
    (ToyOwnerBoyId is not null and ToyOwnerGirlId is null) 
) 

至于选择数据,可以使用外部连接:

select ... 
from toys 
left join boys on boys.boyid = toys.toyownerboyid 
left join girls on girls.girlid = toys.toyownergirlid; 

要找到男孩拥有的玩具:

select ... 
from toys 
where toyownerboyid is not null; 
+0

这听起来也很完美。 – user3340627 2014-11-25 14:58:33

0

这是一个不好的设计,鉴于一分集(一列,是ToyOwnerId)被称为不同的表,无论是作为一个单列FK到一列PK。那么显而易见的问题是:你如何拥有类似PK的不同牌桌?而且我看到你已经回答了,通过回答各个表的数据列是不同的。这是拥有不同表格的好理由。但是,那么,如何解决FK问题呢? (我明白这些“男孩”和“女孩”不是真正的实体)。你可以做的是做一个BoyToy和一个GirlToy桌子。如果您的数据列非常少(数据=非PK和非FK),那么这是一个完美的解决方案。不是?

+0

谢谢你的回答。这将是一个很好的解决方案,如果它只是一个玩具表,但我有2或3个玩具般的桌子,这意味着我将不得不将它们全部翻倍 – user3340627 2014-11-25 15:02:24

+1

行。那么,这取决于这些“玩具般”的事物是如何相互关联的。您需要查看每次更改的影响:结构表差异会导致完全不同的INSERT/UPDATE/DELETE命令,并且您也必须注意这一点。一个简单的表格设置有时会导致编码恶梦。更不用说:如果你可以避免触发器,并依靠PK/FK,后者在我看来是最好的解决方案。 – tvCa 2014-11-25 15:17:20