【问题标题】:Is it antipattern to create a junction table with more than two foreign keys?创建具有两个以上外键的联结表是反模式吗?
【发布时间】:2020-10-24 02:12:38
【问题描述】:

我正在为学校管理设计一个数据库。

这里不是一所学校,而是多所学校,有自己的学生、班级、教师和科目。

这是要求。

• 一所学校可以有多个班级

• 一个类可以有许多子类

• 许多学生可以属于一个班级的一个部分

• 许多教师可以属于一个班级的一个部分

• 许多科目可以属于一个类的一个部分

• 学校想要管理班级

• 学校想要管理部门

• 学校希望在班级的某个部分管理科目

• 学校想为班级某个部分的某个科目分配一名教师

• 学校可以为学生分配班级的一个部分

另外,有些学校可以有名为一、二、三的班级,有些可能有一、二、三等。部分或子类也一样

对于实体 School 和 Teacher 来说,事情是直截了当的。以下是我对他们的方法。

School
--------------
id 
name
...

Teacher
--------------
id
school_id
name

但我在为学校规划班级和部门时遇到了问题。

我尝试创建另外两个实体类和部分,并给它们一个学校的外键

SchoolClass
-----------------
school_id
class_name
...


SchoolSection
----------------
school_id
section_name
...

为了将学校的班级映射到它的所有部分,我创建了一个联结表,因为它将是多对多的关系。

SchoolClassSection
---------------------------------------------------------
school_class_id
school_section_id  

但正如我上面提到的,我还需要将科目和教师添加到课程的某个部分,所以尝试如下所示。

SchoolClassSections
---------------------------------------------------------
school_class_id
school_section_id
subject_id
teacher_id

但现在我在联结表中有四个外键。

在一个联结表中有两个以上的外键是否没有问题?

另外,我也需要添加学生,但我现在想不通如何进一步提高班级、部分的学生关系?

我可以像下面这样的一件事

student
-----------
school_id
school_class_section_id // but if SchoolClassSections can have subject_id and teacher_id too it will become confusing

【问题讨论】:

    标签: mysql sql database database-design many-to-many


    【解决方案1】:

    不,它不是“反模式”。有很多例子表明联结表可能有两个以上的外键:

    • 医生预约可能有医生、患者和诊所。
    • 零售订单可能包含客户、位置和付款类型。
    • 在线订阅可能包含客户 ID、产品、付款类型和来源。

    这些只是其他领域的一些示例(它们甚至不包括日期维度)。一个表有多个外键并不少见。

    【讨论】:

    • 您能否验证我是否在架构中遗漏了某些内容?我现在不知道如何进一步了解班级、部分的学生关系。
    【解决方案2】:

    由于这里的时间限制,我没有分析您的架构。

    但是无论从关系的角度还是从 SQL 的角度来看,对于具有两个以上外键的表或联结表,都没有问题。事实上,这很常见。

    【讨论】:

    • 您能否验证我是否在架构中遗漏了某些内容?我现在无法弄清楚如何进一步促进班级、部分的学生关系
    • @SharpBlade:首先,将您的需求表达为功能依赖关系。这就是你所缺少的。
    【解决方案3】:

    有些概念,尤其是 OO 概念,并不适合 SQL。

    SQL 有“唯一”:

    • 1:1 关系(通常不应该使用)
    • 1:many(通过一个表中的链接实现到另一个)
    • many:many(需要单独的“联结”表)

    在每种情况下,“1”可以退化为“0”,“many”可以退化为“1”或“0”。通常“0”没有明确表示,而是通过没有行来表示。

    创建模式:

    1. 想想应该有什么“实体”表。 (学生、班级、学校等)
    2. 创建关系,以 1:many 和 many:many 的方式思考。
    3. (可选)为链接建立FOREIGN KEYs。 (为了参照完整性;隐式创建INDEX
    4. 确保相应的列是INDEXed。 (为了表现)

    稍后...

    1. SELECTsUPDATEs
    2. 使用这些查询来决定是否需要其他索引。

    您的问题主要是关于 many:many 表。

    • 基本的 many:many 表正好有 2 列(链接到其他两个表)
    • 基本有两个复合索引(PRIMARY KEY(a,b)INDEX(b,a)
    • 当然,多:多:多(不常见,但合理)
    • 为关系的属性添加列(也不常见,但可以)
    • 为依赖于这些属性的查询添加复合索引(以提高性能)

    更多讨论many:many:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table

    【讨论】:

    • 感谢您的链接,非常感谢您的建议。但请回答我问题的第二部分。我现在想不通如何进一步促进班级、部分的学生关系?
    • @SharpBlade - 所以,有时它会连续进行多次提交?连续多个delete t1?也许甚至在做其他事情之前插入 20 行?并且没有有用的索引,所以所有的动作都有效地锁定了整个表?真是一团糟。
    • 这是我该如何解决的问题?
    • 不知道我最后的评论是不是针对其他问答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 2020-08-04
    • 2021-12-30
    • 2019-02-04
    • 2011-04-21
    相关资源
    最近更新 更多