如何在 MySQL 中的 3+ table 秒之间创建中介 table

How do I create an intermediary table between 3+ tables in MySQL

我正在构建一个相对简单的数据库,它有 4 个实体:

问题、考试和幻灯片 table 都有不同的模式,除了每个 table 中每条记录的唯一 ID 字段。

我现在想使用中间件 table,moduleParts,到:

此外,一个模块可能多次包含相同的 'part',并且一个部分可能分配给多个模块。

这个table中的每条记录都有自己的ID,'part'所属模块的ID,还有...好吧,我不知道用什么来存储参考问题/考试/幻灯片。

  1. 我们不能使用项目自己的 table 中的 ID,因为这在 moduleParts table 中不是唯一的(考试4 / 模块 2 与幻灯片 4 / 模块 2)
  2. 冲突
  3. 在旁边存储适当的 table 名称似乎很笨拙
  4. 创建一个新的 table、modulePartsTypes,它是模块部件类型及其各自的 table 名称的列表 - 笨拙且比数字 2.

自从我不得不计划一个 DB 以来已经有一段时间了,所以...是否有一个明显的/最佳实践的解决方案我错过了?

方法一:

我这样做的方法是用每个 "parts"

创建 link table

这样你就可以将 ModulesLessonsModulesExamsModulesSlides 作为三个不同的 tables.

每个 table 将有两个主键,每个主键都是各自 table 的外键。

例如,ModulesLessons 将有 ModuleIDLessonID。这两个键都是主键(因此是唯一的),ModuleID 将是 Modules 上的 id 的外键,而 LessonID 将使用课程.

中的外键

通过这种方法,您不会遇到上述冲突问题。但是,它确实假设一个模块每个模块只有一次课程,同样适用于考试和幻灯片。它将需要三个 table,但一旦建成,您将能够拥有所需的多对多灵活性。

方法二

您可以制作一个 table 具有更多主键,如您所描述的那样,称为 ModulesParts 并为 ModuleID、[=12 创建主键=]、ExamIdSlideID

这应该可行,但对正在发生的事情的分析可能会更加混乱。然而,这种方法的优点之一是创建另一个键非常容易,它有类似 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 lessonsexams 具有对复合 table modules 的引用(外键)属性,即也是它们的主键的一部分,由 module_idsequence_no 组成。在这种方法中,属性 sequence_no 具有双重作用:它既是相对标识符(作为 PK 的一部分),又对组件(课程和考试)的顺序进行编码。这是一种简化的方法,只有在没有其他 table 引用这些组件 table 的情况下才可以。否则,必须添加另一个相对标识符属性(例如 lesson nameexam date)以替换 PK 中的 sequence_no