数据建模是在关系图中表示现实世界的艺术。你的模式是正确的,但它是真的吗?
考虑一下,什么是 CLASS?这是一个老师、一个科目和一个年级。这些是你的关系。此外,您希望强制执行主题适用于该年级并且教师可以在该年级教授该主题的规则。
我认为您的问题在于在交叉表中使用代理键。这些是代表您的多对多关系的表:teacher_subject
, grade_subject
. 无论如何,这些都是合成表,而且它们只包含键。因此,复合主键就足够了。
代理主键没有意义,所以我们需要定义一个唯一的约束grade_subject(subject_id, grade_id)
来确保我们没有两个记录('PHYSICS','YEAR 2')。鉴于这grade_subject
是一个没有其他列的交集表,添加代理键是没有意义的。代理键的价值在于最小化业务键更改的影响。但grade_subject
没有业务密钥,只有两个代理密钥,subject_id
并且grade_id
.
这在定义参照完整性时具有优势。
所以我会这样解决你的问题:
grade_subject
----------------
grade_id
subject_id
primary key (grade_id, subject_id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
teacher_subject
---------------------
teacher_id
grade_id
subject_id
primary key (teacher_id,grade_id, subject_id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
foreign key (teacher_id) reference teacher (teacher_id)
foreign key (grade_id,subject_id) reference grade_subject (grade_id,subject_id)
Class
-----------------------------------
id
teacher_id
grade_id
subject_id
primary key (id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
foreign key (teacher_id) reference teacher (teacher_id)
foreign key (grade_id,subject_id) reference grade_subject (grade_id,subject_id)
foreign key (teacher_id,grade_id,subject_id) reference teacher_subject (teacher_id,grade_id,subject_id)
这可能看起来像一堆外键,我可以在审查阶段设想一些争论。(我包括外键,grade_subject
所以我有一些要让步的东西,我不太在意,所以可以让步)。
但我不喜欢通过诸如 TEACHER_SUBJECT 之类的附属关系强制执行诸如 CLASS_SUBJECT 之类的重要数据关系。我不想加入 TEACHER_SUBJECT 和 SUBJECT_GRADE 才能将 CLASS 加入 SUBJECT。
现在,当后者间接强制前者时,为什么我选择将参照完整性约束包括到单父表和交叉表?因为它使模型中的关系更加清晰。我在模型中强调,因为在物理数据库中我可能会选择省略单表外键,或者禁用它们,并信任交集表的关系完整性。
关于三列复合的一些事情让我感到困惑,我认为是这样的:它没有充分标准化。您可能有一个特殊情况,但更通用的模型是两条规则,TEACHER_SUBJECT 和 TEACHER_GRADE。看起来像这样
teacher_subject
---------------------
teacher_id
subject_id
primary key (teacher_id, subject_id)
foreign key (subject_id) reference subject (subject_id)
foreign keye (teacher_id) reference teacher (teacher_id)
teacher_grade
---------------------
teacher_id
grade_id
primary key (teacher_id,grade_id)
foreign key (grade_id) reference grade (grade_id)
foreign key (teacher_id) reference teacher (teacher_id)
Class
-----------------------------------
id
teacher_id
grade_id
subject_id
primary key (id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
foreign key (teacher_id) reference teacher (teacher_id)
foreign key (grade_id,subject_id) reference grade_subject (grade_id,subject_id)
foreign key (teacher_id,subject_id) reference teacher_subject (teacher_id,subject_id)
foreign key (teacher_id,grade_id) reference teacher_grade (teacher_id,grade_id)
当然,如果您仍然想强制执行 Drury 先生只能向四年级学生教授数学和向六年级学生教授物理的规则,您将需要一个 TEACHER_SUBJECT_GRADE 表。
您的数据模型没有解决的一件事是调度问题。学校时间表必须网格化,因此班级需要适应预先确定的网格。您可能需要将时间表的时段定义为单独的表格并将 CLASS 链接到该表格。班级也需要教室。那是另一张桌子。