以下是我所面临的设计问题的类似(和简化)示例:
假设您有学生,班级和成绩。学生可以参加许多不同的课程。每个班级都有很多不同的学生。每个(学生,班级)对都有一个等级。
我应该布局数据库(mysql数据库),如:
选项1)
students table - (student_id, student_name)
classes table - (class_id, class_name)
students_classes table - (student_class_id, student_id, class_id)
grades table - (student_class_id, grade)
选项2)
students table - (student_id, student_name)
classes table - (class_id, class_name)
grades table - (student_id, class_id, grade)
或者它应该被设计为其他东西?选项2现在看起来更简单了,但是在将来,我可能需要与每个(student_id,class_id)对相关的其他统计数据(在这种情况下,选项1看起来好一点吗?选项1仍然感觉有点过于复杂)。/ p>
你推荐什么?感谢。
答案 0 :(得分:3)
我会亲自前往选项2。成绩的复合主键没有任何问题,它可以捕获数据模型中所需的信息。
在选项1中,除了拥有代理键外,students_classes没有任何意义。
在看到其他答案后编辑:
答案 1 :(得分:3)
选项3)
students table - (student_id, student_name)
classes table - (class_id, class_name)
students_classes table - (student_class_id, student_id, class_id, grade)
成绩是学生班级的一个属性。
除非等级有可能成为一个完整的实体。在这种情况下:
选项4)
students table - (student_id, student_name)
classes table - (class_id, class_name)
students_classes table - (student_class_id, student_id, class_id)
grades table - (grade_id, grade, student_class_id)
答案 2 :(得分:1)
选项2是正确的,除了它应该被称为 student_class
,反映其n :: n函数或注册为实体。而(student_id, class_id)
就是PK。
成绩(如您所示)是对该复合键的1 :: 1依赖关系(不在一个或另一个元素上),而在其他任何内容上都没有,因此它是student_class
的属性。< / p>
因此student_class
在3NF。
如果人们没有开始盲目地将Id
iot列放在移动的所有内容上,就像使用选项1一样,他们将能够更好地理解数据,从而更好地规范化。那个(选项1中的Id
iot列作为起点)干扰了你(student_id, class_id)
是标识符的直觉;没有额外的Id
iot列及其附加索引是必要的。然后当你开始评估grade
时,它对PK的依赖是显而易见的。
Id
iot列会破坏数据库的Relational功能。如果您在层次结构中说了三个表,并且需要从顶部和底部表中获取一些列,则必须通过中间表。如果您有关系标识符,而不是Idiot列,则必须从底部表到顶部表,而不必阅读中间表。
在“规范化”数据库中有如此多的连接只是一半。完全的事实是,由于数据库没有正确规范化,是的,你被迫加入了比必要的更多的连接。在具有相同表的真正规范化数据库中,代码需要更少的连接。
以下是最近作业的简化版>Data Model for a College<。
>IDEF1X Notation<适用于那些需要解释符号的人。
请注意,只需要一个代理键。
看看你是否能够理解标识符(实线)是传给子孙的;他们有,并传达意义
当我们有一个非常好的PersonId(外键并且已经是唯一的)时,为TeacherId,StudentId,StaffId添加代理键是愚蠢的。 (这些列的名称用于标识其角色。)
所有业务规则均以DDL实现:FK约束;检查约束;规则。
房间有一个4列的复合键;提供3列复合键;两者一起消除了双重预订。
提供PK和学生PK一起构成了入学PK(与本课题相同; PK由不同的专栏组成,全部都是这样)。
答案 3 :(得分:0)
我是第三范式的粉丝,你有单独的学生,班级和成绩表,并将它们与多对多表格(如ClassStudent和GradeClass)联系起来。
但这取决于您将来如何维护它。归根结底,它归结为未来的扩展和可维护性。这就是为什么我更喜欢3NF。
修改强>
Axn的answer比我的要好得多。
答案 4 :(得分:-1)
这一切都取决于,真的。选项1可能是执行此应用程序的最强大方法;选项2可能会让您更快地完成此迭代。将来自选项2的变更 - > 1将来是痛苦的吗?你有多确定需要额外的灵活性?
我建议只选择选项1.查询不会那么复杂,如果你使用的是ORM(比如ActiveRecord for Rails,很多),那么差异实际上是空的。