我正在创建一个网站,人们可以在其中对酒类(“烈酒”)进行评分/评论。鉴于某些烈酒在不同瓶子之间可能存在很大差异,我希望用户可以选择评论烈酒本身,或者他们可以选择评论该烈酒的特定瓶子。
考虑下面的表 (SQL Server):
Spirits
+--------+------------------+
| Column | Type |
+--------+------------------+
| Id | uniqueidentifier |
| Name | nvarchar(255) |
+--------+------------------+
Bottles
+----------+------------------+
| Column | Type |
+----------+------------------+
| Id | uniqueidentifier |
| SpiritId | uniqueidentifier |
+----------+------------------+
Ratings
+----------+------------------------+
| Column | Type |
+----------+------------------------+
| Id | uniqueidentifier |
| SpiritId | uniqueidentifier |
| BottleId | uniqueidentifier, null |
| Score | int |
+----------+------------------------+
我是否Ratings
正确接近桌子?如果是这样,我如何强制它BottleId
是 的孩子SpiritId
?
或者,我应该要求SpiritId
or BottleId
,但不能同时要求两者(有没有办法在数据库中强制执行此要求?)
我确信已经有人问过这样的问题,但我自己在表达它时遇到了足够的麻烦,因此我的搜索尝试没有产生任何有用的结果。谢谢。
实现此目的的一种方法是在
Bottles
表SpiritId
和BottleId
列上使用复合备用键(唯一约束)。然后,该Ratings
表可以有一个外键引用该Bottles
表的两列,以确保烈酒和瓶子匹配。请注意,外键可以引用唯一约束或唯一索引的列,而不仅仅是主键。NULL
不会检查具有外键值的行的引用完整性,因此NULL
只要 SpiritId 有效,就允许使用 BottleId 进行评级,并由外键约束单独强制执行SpiritId
。示例 DDL 和数据:
我不认为你的设计有什么明显的错误。
您已经在表中通过不可为空的外键字段引用
Bottles
a 来强制执行这一点。在实践中,您需要确保实际创建一个外键对象来强制执行该关系。Spirit
SpiritId
您也可以构建它的另一种方法是为
SpiritRatings
vs建立一个单独的表BottleRatings
。您不必这样做,因为乍一看,您当前的设计对我来说似乎没问题,但如果您向仅适用于一个而不适用于另一个的评级添加列,您可能会发现这种替代设计将来会更有利。