如何在 MySQL 中的 3+ table 秒之间创建中介 table
How do I create an intermediary table between 3+ tables in MySQL
我正在构建一个相对简单的数据库,它有 4 个实体:
- Modules,存储在modules table中,每个都有一个唯一的id,(在现实世界中)是由任意数量的...
- 问题,存储在问题 table
- Exams,存储在exams table
- 和Slides,存储在slides table
问题、考试和幻灯片 table 都有不同的模式,除了每个 table 中每条记录的唯一 ID 字段。
我现在想使用中间件 table,moduleParts,到:
- 存储构成模块的所有 'parts'(考试、问题和幻灯片)。
- 存储模块中各部分的顺序
此外,一个模块可能多次包含相同的 'part',并且一个部分可能分配给多个模块。
这个table中的每条记录都有自己的ID,'part'所属模块的ID,还有...好吧,我不知道用什么来存储参考问题/考试/幻灯片。
- 我们不能使用项目自己的 table 中的 ID,因为这在 moduleParts table 中不是唯一的(考试4 / 模块 2 与幻灯片 4 / 模块 2)
冲突
- 在旁边存储适当的 table 名称似乎很笨拙
- 创建一个新的 table、modulePartsTypes,它是模块部件类型及其各自的 table 名称的列表 - 笨拙且比数字 2.
自从我不得不计划一个 DB 以来已经有一段时间了,所以...是否有一个明显的/最佳实践的解决方案我错过了?
方法一:
我这样做的方法是用每个 "parts"
创建 link table
这样你就可以将 ModulesLessons、ModulesExams 和 ModulesSlides 作为三个不同的 tables.
每个 table 将有两个主键,每个主键都是各自 table 的外键。
例如,ModulesLessons 将有 ModuleID
和 LessonID
。这两个键都是主键(因此是唯一的),ModuleID
将是 Modules 上的 id 的外键,而 LessonID
将使用课程.
中的外键
通过这种方法,您不会遇到上述冲突问题。但是,它确实假设一个模块每个模块只有一次课程,同样适用于考试和幻灯片。它将需要三个 table,但一旦建成,您将能够拥有所需的多对多灵活性。
方法二
您可以制作一个 table 具有更多主键,如您所描述的那样,称为 ModulesParts 并为 ModuleID
、[=12 创建主键=]、ExamId
和 SlideID
这应该可行,但对正在发生的事情的分析可能会更加混乱。然而,这种方法的优点之一是创建另一个键非常容易,它有类似 ModuleOrder
的东西,因此您可以轻松地组织模块中的元素,使其按照您希望它们出现的顺序出现.
这是一个演示。请注意,您可以使用 0 来指示不应显示的项目(如最后一行)。事实上,将这些默认设置为 0 可能是有意义的,除非您希望两个项目一起出现。
ModuleID LessonID ExamId SlideID Module Order
1 1 1 1 1
1 1 1 2 4
1 1 2 1 2
1 2 1 1 3
2 1 1 1 1
2 1 2 2 2
2 2 1 1 3
2 0 0 2 4
方法 3
如果您需要在一个模块中多次使用课程或考试等部分,还有另一种方法。
创建 2 个主键,其中一个是之前的 ModuleID(模块的外键)和 ModuleOrder,它只存在于此 table。由于项目只能按顺序出现在这个 table 上,每个模块只有一个数字顺序。 LessonID、ExamID 和 SlideID 等其他项目可以作为非唯一索引存在,因此您可以选择让同一考试在同一模块中出现两次。
不清楚给定的课程、幻灯片或考试是否可以作为多个模块的一部分。如果不是,则只需向这 3 个 table 中的每一个添加一个 "module_id",然后将它们加入您的查询:
SELECT ...
FROM modules
JOIN lessons ON lessons.module_id = modules.id
UNION
SELECT ...
FROM modules
JOIN slides ON slides.module_id = modules.id
UNION
SELECT ...
FROM modules
JOIN exams ON exams.module_id = modules.id
ORDER BY modules.id, ...
或者,也许更简单,对每个不同的部分执行 3 个不同的查询,因为您可能在每个 table 中有足够多的不同列,以至于 UNION 会很尴尬。
我不明白将 "slides"(我猜你的意思是演示文稿)作为模块部分包括在内的目的。我认为它们是课程的一部分。这就是我在下面的讨论中省略它们的原因。
从 UML class 图形式的信息设计模型开始总是好的:
从这样的信息设计模型中,我们可以推导出各种数据模型,包括SQL数据库模型,可以用以下方式描述:
modules(
id PK,
name
)
lessons(
module_id FK(modules),
sequence_no,
title
PK( module_id, sequence_no)
)
exams(
module_id FK(modules),
sequence_no,
description
PK( module_id, sequence_no)
)
PK 代表 PRIMARY KEY,FK 代表 FOREIGN KEY。
请注意,组件 tables lessons
和 exams
具有对复合 table modules
的引用(外键)属性,即也是它们的主键的一部分,由 module_id
和 sequence_no
组成。在这种方法中,属性 sequence_no
具有双重作用:它既是相对标识符(作为 PK 的一部分),又对组件(课程和考试)的顺序进行编码。这是一种简化的方法,只有在没有其他 table 引用这些组件 table 的情况下才可以。否则,必须添加另一个相对标识符属性(例如 lesson name
和 exam date
)以替换 PK 中的 sequence_no
。
我正在构建一个相对简单的数据库,它有 4 个实体:
- Modules,存储在modules table中,每个都有一个唯一的id,(在现实世界中)是由任意数量的...
- 问题,存储在问题 table
- Exams,存储在exams table
- 和Slides,存储在slides table
问题、考试和幻灯片 table 都有不同的模式,除了每个 table 中每条记录的唯一 ID 字段。
我现在想使用中间件 table,moduleParts,到:
- 存储构成模块的所有 'parts'(考试、问题和幻灯片)。
- 存储模块中各部分的顺序
此外,一个模块可能多次包含相同的 'part',并且一个部分可能分配给多个模块。
这个table中的每条记录都有自己的ID,'part'所属模块的ID,还有...好吧,我不知道用什么来存储参考问题/考试/幻灯片。
- 我们不能使用项目自己的 table 中的 ID,因为这在 moduleParts table 中不是唯一的(考试4 / 模块 2 与幻灯片 4 / 模块 2) 冲突
- 在旁边存储适当的 table 名称似乎很笨拙
- 创建一个新的 table、modulePartsTypes,它是模块部件类型及其各自的 table 名称的列表 - 笨拙且比数字 2.
自从我不得不计划一个 DB 以来已经有一段时间了,所以...是否有一个明显的/最佳实践的解决方案我错过了?
方法一:
我这样做的方法是用每个 "parts"
创建 link table这样你就可以将 ModulesLessons、ModulesExams 和 ModulesSlides 作为三个不同的 tables.
每个 table 将有两个主键,每个主键都是各自 table 的外键。
例如,ModulesLessons 将有 ModuleID
和 LessonID
。这两个键都是主键(因此是唯一的),ModuleID
将是 Modules 上的 id 的外键,而 LessonID
将使用课程.
通过这种方法,您不会遇到上述冲突问题。但是,它确实假设一个模块每个模块只有一次课程,同样适用于考试和幻灯片。它将需要三个 table,但一旦建成,您将能够拥有所需的多对多灵活性。
方法二
您可以制作一个 table 具有更多主键,如您所描述的那样,称为 ModulesParts 并为 ModuleID
、[=12 创建主键=]、ExamId
和 SlideID
这应该可行,但对正在发生的事情的分析可能会更加混乱。然而,这种方法的优点之一是创建另一个键非常容易,它有类似 ModuleOrder
的东西,因此您可以轻松地组织模块中的元素,使其按照您希望它们出现的顺序出现.
这是一个演示。请注意,您可以使用 0 来指示不应显示的项目(如最后一行)。事实上,将这些默认设置为 0 可能是有意义的,除非您希望两个项目一起出现。
ModuleID LessonID ExamId SlideID Module Order
1 1 1 1 1
1 1 1 2 4
1 1 2 1 2
1 2 1 1 3
2 1 1 1 1
2 1 2 2 2
2 2 1 1 3
2 0 0 2 4
方法 3
如果您需要在一个模块中多次使用课程或考试等部分,还有另一种方法。
创建 2 个主键,其中一个是之前的 ModuleID(模块的外键)和 ModuleOrder,它只存在于此 table。由于项目只能按顺序出现在这个 table 上,每个模块只有一个数字顺序。 LessonID、ExamID 和 SlideID 等其他项目可以作为非唯一索引存在,因此您可以选择让同一考试在同一模块中出现两次。
不清楚给定的课程、幻灯片或考试是否可以作为多个模块的一部分。如果不是,则只需向这 3 个 table 中的每一个添加一个 "module_id",然后将它们加入您的查询:
SELECT ...
FROM modules
JOIN lessons ON lessons.module_id = modules.id
UNION
SELECT ...
FROM modules
JOIN slides ON slides.module_id = modules.id
UNION
SELECT ...
FROM modules
JOIN exams ON exams.module_id = modules.id
ORDER BY modules.id, ...
或者,也许更简单,对每个不同的部分执行 3 个不同的查询,因为您可能在每个 table 中有足够多的不同列,以至于 UNION 会很尴尬。
我不明白将 "slides"(我猜你的意思是演示文稿)作为模块部分包括在内的目的。我认为它们是课程的一部分。这就是我在下面的讨论中省略它们的原因。
从 UML class 图形式的信息设计模型开始总是好的:
从这样的信息设计模型中,我们可以推导出各种数据模型,包括SQL数据库模型,可以用以下方式描述:
modules(
id PK,
name
)
lessons(
module_id FK(modules),
sequence_no,
title
PK( module_id, sequence_no)
)
exams(
module_id FK(modules),
sequence_no,
description
PK( module_id, sequence_no)
)
PK 代表 PRIMARY KEY,FK 代表 FOREIGN KEY。
请注意,组件 tables lessons
和 exams
具有对复合 table modules
的引用(外键)属性,即也是它们的主键的一部分,由 module_id
和 sequence_no
组成。在这种方法中,属性 sequence_no
具有双重作用:它既是相对标识符(作为 PK 的一部分),又对组件(课程和考试)的顺序进行编码。这是一种简化的方法,只有在没有其他 table 引用这些组件 table 的情况下才可以。否则,必须添加另一个相对标识符属性(例如 lesson name
和 exam date
)以替换 PK 中的 sequence_no
。