如何在MySQL中的3个表之间创建中间表

时间:2015-04-01 18:22:23

标签: mysql database database-design

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

  • 模块,存储在 modules 表中,每个都有一个唯一的ID,(在现实世界中)由任意数量的...组成...
  • 问题,存储在问题
  • 考试,存储在考试表中
  • 幻灯片,存储在幻灯片表中

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

我现在想要使用中间表 moduleParts 来:

  • 存储构成模块的所有“部分”(考试,问题和幻灯片)。
  • 存储模块中部件的顺序

此外,模块可以多次包含相同的“部分”,并且可以将部分分配给多个模块。

此表中的每条记录都有自己的ID,“部分”所属模块的ID以及......好吧,我不知道用什么来存储对问题/考试/幻灯片的引用

  1. 我们不能在自己的表中使用项目自己的ID,因为这在 moduleParts 表中是不唯一的(考试4 /模块2与幻灯片4 /模块2冲突)< / LI>
  2. 在旁边存储适当的表名称似乎很笨拙
  3. 创建一个新表 modulePartsTypes ,这是一个模块部件类型列表及其各自的表名 - 比数字2更笨拙,更复杂。
  4. 已经有一段时间了,因为我必须计划一个数据库,所以...我有一个明显的/最佳实践解决方案吗?

3 个答案:

答案 0 :(得分:1)

方法1:

我这样做的方法是使用每个“部分”

创建链接表

通过这种方式,您可以将 ModulesLessons ModulesExams ModulesSlides 作为三个不同的表。

然后每个表都有两个主键,每个主键都是各自表的外键。

例如, ModulesLessons 会有ModuleIDLessonID。这两个密钥都是主键(因此是唯一的),ModuleID将是模块上的id的外键,而LessonID将使用来自的外键的

使用这种方法,您不会遇到上述冲突的问题。但是,假设模块每个模块只有一个课程,对于考试和幻灯片也是如此。它需要三个表,但一旦构建,您将能够获得所需的多对多灵活性。

方法2

您可以创建一个包含更多主键的表,例如您描述的名为 ModulesParts 的表,并为ModuleIDLessonIDExamId创建主键,和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,它们只存在于此表中。由于项目只能按此顺序显示,因此每个模块只会有一个数字顺序。其他项目(如LessonID,ExamID和SlideID)可以作为非唯一索引存在,因此您可以选择在同一模块中出现两次相同的检查。

答案 1 :(得分:1)

目前还不清楚给定的课程,幻灯片或考试是否可以成为多个模块的一部分。如果没有,那么只需添加&#34; module_id&#34;到这3个表中的每个表,然后将它们加入到您的查询中:

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个不同的查询,因为你可能在每个表中有足够不同的列,UNION会很尴尬。

答案 2 :(得分:1)

我不明白包含&#34;幻灯片的目的&#34; (我猜你的意思是演示文稿)作为模块部分。我认为它们是教学部分。这是我在下面的讨论中省略它们的原因。

以UML类图的形式开始使用信息设计模型总是好的:

enter image description here

从这样的信息设计模型中,我们可以推导出各种数据模型,包括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。

请注意,组件表lessonsexams具有复合表modules的引用(外键)属性,它也是由{{1}组成的主键的一部分}和module_id。在这种方法中,属性sequence_no用于双重角色:它既是相对标识符(通过作为PK的一部分),也编码组件的顺序(课程和考试)。这是一种简化的方法,只有在没有其他表引用这些组件表时才可以。否则,必须添加另一个相对标识符属性(例如sequence_nolesson name)以替换PK中的exam date