我正在构建一个相对简单的数据库,它有4个实体:
除了每个表中每条记录的唯一ID字段外,问题,考试和幻灯片表都有不同的模式。
我现在想要使用中间表 moduleParts 来:
此外,模块可以多次包含相同的“部分”,并且可以将部分分配给多个模块。
此表中的每条记录都有自己的ID,“部分”所属模块的ID以及......好吧,我不知道用什么来存储对问题/考试/幻灯片的引用
已经有一段时间了,因为我必须计划一个数据库,所以...我有一个明显的/最佳实践解决方案吗?
答案 0 :(得分:1)
我这样做的方法是使用每个“部分”
创建链接表通过这种方式,您可以将 ModulesLessons , ModulesExams 和 ModulesSlides 作为三个不同的表。
然后每个表都有两个主键,每个主键都是各自表的外键。
例如, ModulesLessons 会有ModuleID
和LessonID
。这两个密钥都是主键(因此是唯一的),ModuleID
将是模块上的id的外键,而LessonID
将使用来自的外键的课强>
使用这种方法,您不会遇到上述冲突的问题。但是,假设模块每个模块只有一个课程,对于考试和幻灯片也是如此。它需要三个表,但一旦构建,您将能够获得所需的多对多灵活性。
您可以创建一个包含更多主键的表,例如您描述的名为 ModulesParts 的表,并为ModuleID
,LessonID
,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
如果您需要在模块中多次使用课程或考试等部分,还有另一种方法。
创建2个主键,其中一个是以前的ModuleID(模块的外键)和ModuleOrder,它们只存在于此表中。由于项目只能按此顺序显示,因此每个模块只会有一个数字顺序。其他项目(如LessonID,ExamID和SlideID)可以作为非唯一索引存在,因此您可以选择在同一模块中出现两次相同的检查。
答案 1 :(得分:1)
目前还不清楚给定的课程,幻灯片或考试是否可以成为多个模块的一部分。如果没有,那么只需添加" module_id"到这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)
我不明白包含"幻灯片的目的" (我猜你的意思是演示文稿)作为模块部分。我认为它们是教学部分。这是我在下面的讨论中省略它们的原因。
以UML类图的形式开始使用信息设计模型总是好的:
从这样的信息设计模型中,我们可以推导出各种数据模型,包括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。
请注意,组件表lessons
和exams
具有复合表modules
的引用(外键)属性,它也是由{{1}组成的主键的一部分}和module_id
。在这种方法中,属性sequence_no
用于双重角色:它既是相对标识符(通过作为PK的一部分),也编码组件的顺序(课程和考试)。这是一种简化的方法,只有在没有其他表引用这些组件表时才可以。否则,必须添加另一个相对标识符属性(例如sequence_no
和lesson name
)以替换PK中的exam date
。