por*_*ton 0 foreign-key database-design
“组”是一群学生。“话题”是课程的话题。
每个组对应一个主题。(因此每个主题可能有多个组。)
一个学生对应多个组,但每个主题最多一个组。
如何根据 MySQL 中的 UNIQUE 索引和外键实现这一点?
这是一个常见的问题。“诀窍”是:
Groups
- 除了主键 - 上的冗余唯一约束(Topic, Group)
。 Topic
在Participates
关系中添加属性和 Participates
,Groups
因此它Topic
不仅包括Group
.然后您可以添加一个唯一约束Participates (Pupil, Topic)
(意味着学生只能参与一个主题一次,而不是两次或更多,这是想要的结果。)
Topics
Topic PK
Lessons
Lesson PK
Topic FK -> Topics
Groups
Group PK UQ1
Topic UQ1 FK -> Topics
Pupils
Pupil PK
PupilParticipatesInGroup
Pupil PK UQ1 FK1 -> Pupils
Group PK FK2 -> Groups
Topic UQ1 FK2
Run Code Online (Sandbox Code Playgroud)附录
Abbreviation Constraint
------------ -----------
PK Primary Key
UQ Unique
FK Foreign Key
Run Code Online (Sandbox Code Playgroud)
请注意,设计已经完成,3NF
并且Topics
只有在大多数 DBMS 中的实现才需要冗余的唯一约束(因此强制执行外键。)
唯一的另一个问题是Group -> Topic
关系中的依赖Participates
关系导致架构违反BCNF
。
在链接页面的Achievability of BCNF段落中,您将看到已证明并非所有表都可以分解为满足BCNF
并保留原始表中的依赖关系的表。提供的示例与Participates
此处的表格非常相似:
在某些情况下,非 BCNF 表无法分解为满足 BCNF 并保留原始表中的依赖关系的表。Beeri 和 Bernstein 在 1979 年表明,例如,一组函数依赖
{AB ? C, C ? B}
不能用 BCNF 模式表示。 [6] 因此,与前三种范式不同,BCNF 并不总是可以实现的。
尽管如此,让我们再做一个改变,以解决这个问题(如果可以的话!):
让我们来看看如果我们从(好像它从未存在过)Primary Key (Group)
约束中移除(Groups
并把唯一的放在它的位置)会发生什么。让我们也改变主键Participates
- 注意 - 恰好是我们从一开始的目标的唯一约束. 设计变为(前两个表保持不变,因此省略):
Groups
Group PK
Topic PK FK -> Topics
Pupils
Pupil PK
PupilParticipatesInGroup
Pupil PK FK1 -> Pupils
Group FK2 -> Groups
Topic PK FK2
Run Code Online (Sandbox Code Playgroud)
根本没有多余的列。魔法!这Participates
是Groups
and之间常见的多对多关系Pupils
(正如我们的模型所希望的那样),并且两个外键引用相应表的主键。
所以发生了什么事?魔法?(不是真的,不是) 不是Group
仍然是 的候选键Groups
吗?(无论如何,删除它只是一个思想实验。)如果从实际表中省略这个约束,我们会不会失去一些东西?
问题 - 以及为什么上述解决它 - 是您尝试建模的唯一约束需要关系中的Topic
属性Participates
。因此,您必须使用Groups
复合和包含的候选键Topic
。它不一定是(Topic, Group)
。它可能是其他一些组合。还有哪些其他属性Groups
?
如果,例如,有一个属性OrderNo
中Groups
和(Topic, OrderNo
)是唯一的,那么我们能有这样的设计(终于)在没有冗余,没有多余的属性,所有的约束都没有和架构是!BCNF
:
Groups
Group PK
Topic UQ1 FK -> Topics
OrderNo UQ1
Pupils
Pupil PK
PupilParticipatesInGroup
Pupil PK FK1 -> Pupils
Topic PK FK2 -> Groups
OrderNo FK2
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
337 次 |
最近记录: |