我不确定如何提出这个问题,所以我会尽可能清楚地说明一个例子。
在像facebook这样的应用中,个人资料可以拥有多个ProfilePictures。在任何给定时间,其中一个是“选定的”ProfilePicture(假设已经上传了ProfilePicture)。
本能地,我会将其建模为:
Table: Profile
--------------
ProfileID
SelectedProfilePictureId //fk to ProfilePicture
Name, Age, Etc
Table: ProfilePicture
---------------------
ProfilePictureId
ProfileId //fk to Profile, indicating which Profile this picture belongs to
Url, DateTaken, Etc
此时,这些表格相互指向对我而言似乎“错误”。它可以很容易地查询没有SelectedProfilePictures的个人资料或获取个人资料的SelectedPicture,但是插入和更新有点不可思议。
这是不好的形式? Profile表是否应该与ProfilePicture表完全独立?是否存在根据数据库设计理论对此进行建模的“正确”方法,还是由程序员的排泄决定?
答案 0 :(得分:6)
你是对的,这被称为循环引用,你实际上无法使数据库这样做。
一个简单的解决方案是子图片表上的“首选”标志。但是你在这里有一个商业逻辑问题:对于给定的人来说,只有一行是首选。因此,当任何人将新标记作为首选标记时,您必须清除其他标记。
更安全的解决方案是向Profiles和ProfilePictures添加带有外键的第三个表“preferredPictures”。在profileId上使其唯一,因此它永远不会有多个条目。这会强制在插入新条目之前删除先前条目。或者您当然可以更新现有的。
编辑:以回应评论。
1)没有循环引用,因为“个人档案”是两个子表的父级,它不会循环到“个人档案”
Profiles
| |
| +-----> PreferredPicture
| +----->
| |
\|/ |
ProfilePictures
2)首选图片的主键是ProfileId,技术上是Profiles的1:1子表。
答案 1 :(得分:1)
为什么需要将ProfileID保存在ProfilePicture表中?
如果您需要这个,您可能需要第3个表来构建关联:
简档< - > ProfilePictureID
答案 2 :(得分:1)
之前,我曾在其他项目中使用过“循环引用”。
如果Profile.SelectedProfilePictureId为Nullable且ProfilePicture.ProfileId为Mandatory则可以。只有当你强制要求两个fk时,才能得到一个真正的循环引用,这是不可能的。