引用两个表的字段 - 外键冲突

时间:2014-11-25 14:37:22

标签: sql sql-server database-design

请查看下表,了解我的问题的简化版本:

表男孩

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之一

我的问题: 当我尝试插入一个名为Boy的新玩具时,我得到一个错误,即在Girls约束中有foreign key conflict

这是袋子设计还是我仍然可以使用相同的设计和修复?

4 个答案:

答案 0 :(得分:2)

我认为你应该把男孩和女孩的桌子放在一张叫做儿童的桌子上。它会有性别列,有M或F.这将简化事情。

答案 1 :(得分: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;

答案 2 :(得分:1)

它看起来像一个糟糕的设计。为什么不给所有孩子准备一张桌子和一些标记 - 是男孩还是女孩?此外,我真的怀疑你需要ToyOwnerBoyOrGirl字段 - 因为它可以通过从玩具到业主的加入轻松获得。

考虑以下方案:

Table Children
ID
Name
Is_Boy

Table Toys
ID
Name
Owner_ID

在这种情况下,您只需要从玩具到业主的外键,您可能遇到的其他任务将更加简单易用。

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

因此,在这种情况下,您仍然可以将表Children(让我们使用以前的术语)作为" common" 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

答案 3 :(得分:0)

这是一个糟糕的设计,因为一个列集(一列,即ToyOwnerId)被引用到不同的表,两者都是一列FK到一列PK。那么显而易见的问题是:你怎么会有类似PK的不同表?而且我看到你已经回答了,通过回复各个表的数据列是不同的。这是拥有不同表格的一个很好的理由。但是,那么,如何解决FK问题呢? (我知道这些"男孩"和女孩"不是真正的实体)。你可以做的是做一个BoyToy和一个GirlToy表。如果您的数据列很少(数据=非PK和非FK),那么这是一个完美的解决方案。不是吗?