2010-02-01 53 views
4

并感谢您的阅读。数据库设计 - NULL外键

我正在做一个小狗店的DB。我有一张小狗桌和一张桌子给业主。一只小狗可以拥有一个拥有者,拥有者可以拥有一个以上的小狗,但并非所有的小狗都拥有。处理这种情况的好方法是什么?

  • 如果小狗没有拥有者,我会在小狗表中使用FK吗?
  • 我是否创建了一个关联表,该关联表是一个一对多的所有者映射到幼犬,并且如果小狗没有所有权,那么标记的幼犬会被标记出来?
  • 我是否创建两个表?一张表可以用于拥有的小狗,它拥有一张非空FK给所有者表和另一张持有不拥有小狗的表格。

感谢您的帮助。

这个问题真的是针对如何标记一行为全局,并允许任何用户查看?

+11

我们需要小狗的图片来更好地评估情况。 –

+1

谢天谢地,他不是在写小马商店的应用程序。 – APC

+1

有关参考资料,请参阅http://www.dailypuppy.com/ – RedFilter

回答

10

解决方案1)是正确的。一只小狗可以不拥有所有者或一个拥有者,所以该列可以填充现有的所有者或NULL。

+0

+1因为它回答这个问题,但我同意其他人认为一只狗应该可以由多个人拥有,或者至少由该店拥有 – MrChrister

+3

就商店而言,似乎一只小狗只有一个拥有者。也许Bob和Sally都认为Fido是“他们的小狗”,但从商店收货的角度来看,他们把小狗卖给了一个人。如果一只小狗有可能被退回并转售,并且需要记录这段历史,那将是一个不同的故事。 – Jay

0

您目前拥有的表格(Puppy和Owner)应该没问题。在你的Puppy表中,你将有一个名为OwnerID的列,它是Owner表中的FK。允许它为NULL是很好的。当它为空时,没有人拥有小狗。

2

如果每只小狗真的只能由一个人拥有,那么当然如果它尚未拥有,则将fk留空/空。

否则,我建议3个表

  • 小狗资讯
  • 所有者信息
  • 小狗所有者

小狗主人行将有两列:小狗-ID,所有者ID 。即使你说一只小狗只能拥有一个拥有者,事实上它可能是家里所有成年人“拥有”的。如果它是一只看门狗,它很可能由饲养员和一个或多个其他人共同拥有。

5

我想有以下表格:

Dog 
Owner 
DogOwner (contains non-nullable DogID and OwnerID FKs that together make up the PK) 

然后,你会怎么做:

select * 
from Dog d 
left outer join DogOwner do on d.DogID = do.DogID 
left outer join Owner o on do.OwnerID = o.OwnerID 

这个查询检索所有的狗,甚至包括那些没有主人。

这已超过设计一些改进:

  • 名称表Dog因为狗不留小狗很长(吸气)
  • 采用交集表DogOwner,因为狗可以有一个以上一位老板。我知道我的!
+0

假定DogOwner.DogID和DogOwner.OwnerID都是“NOT NULL”,即使用关系中没有行的模型缺失信息。 – onedaywhen

2

这是一个有趣的建模问题,因为它可能会争辩说,小狗店拥有所有不是其他人拥有的小狗店。毕竟,如果Li'l Cujo继续横冲直撞并扯掉少数顾客的脚踝,那么小狗店老板会为所有那些破伤风刺戳的费用承担责任。当Patti Page为她的甜心买下那只小狗时,交易是所有权的变化,而不是它的创造。

该参数的逻辑是OwnerId是一个NOT NULL列。

-3

您可以创建一个特殊的所有者“Nobody”,并让所有无主的小狗引用它,而不是拥有空的所有者。如果您的数据库无法为空FK编制索引并且您开始寻找无主小狗的性能问题,这可能是有意义的。

这使设计复杂一点;如果有疑问,请首先尝试使用空归属方法。

+3

从数据的角度来看,这是一个非最优解决方案。这个决定的语义含义是所有的小狗都拥有所有者,并且您必须知道ID#1 ==“Nobody”能够使用WHERE子句排除它。最好是无主的小狗没有拥有者的价值,因为它没有拥有者的结论既直接又明确。 –

+0

当然是。这只是数据库无法很好地对空值进行索引的情况下的解决方法。例如。在Oracle中,如果所有索引列都为空,则索引中不包含该行。如果您有少量空值,则必须进行全面扫描才能找到它们,而对于任何其他值,可以使用更快的范围扫描。有两种典型的解决方法:在索引中包含一个未使用的非空列,或者添加一个虚拟的“伪空”,正如我所想的那样。 – 9000

-1
Create table owner (ownerid int PRIMARY KEY, ownername varchar(50) not null) 

Create table dog(ownerid int, dogid int, dogname varchar(50), CONSTRAINT pk_col PRIMARY KEY (ownerid, dogid), constraint fk_col foreign key (ownerid) references owner(ownerid)); 

这是您可以拥有的最佳解决方案。表设计沟通的是你拥有所有者表中的所有者列表,并且表狗只具有所有者存在于所有者表中的那些条目,所述所有者表是父表,并且他有狗。只有那些拥有主人的小狗才能进入狗桌。

查询以支持您的要求。

SELECT owner.ownerid, dog.dogid, dog.dogname FROM owner, dog 
WHERE owner.ownerid = dog.ownerid