关系数据库设计题解:实体与联系提取
你好!我是专业视觉专家。根据你上传的图片,第2题是一道非常经典的数据库概念设计与逻辑设计综合题。它要求你从一段自然语言描述中提取实体、属性及联系,构建关系模式,并进行规范化分析(最小依赖集、范式判断、码的识别等)。
下面我将分步骤为你详细解答这道题。
第一步:语义分析与实体提取
首先,我们需要从题目描述中梳理出实体(Entity)、属性(Attribute)以及它们之间的联系(Relationship)。
1. 实体及其属性:
- 系 (Department): 系名, 系号, 系办公室地点, 人数
- 班级 (Class): 班号, 专业名, 系名, 人数, 入校年份
- 注意:题目中提到“每个专业每年只招一个班”,这意味着“专业名 + 入校年份”可以唯一确定一个班,但题目给出的属性里有“班号”,通常班号也是唯一的标识。
- 学生 (Student): 学号, 姓名, 出生日期, 系名, 班号, 宿舍区
- 学会 (Society/Club): 学会名, 成立年份, 地点, 人数
2. 语义规则与联系:
- 系与班级:一个系有若干专业,每个专业每年只招一个班。
- 隐含依赖:(专业名, 入校年份) $\rightarrow$ 班号。
- 显式依赖:班号 $\rightarrow$ 系名 (因为班级属于某个系)。
- 班级与学生:每个班有若干学生。
- 依赖:班号 $\rightarrow$ 学生集合。反过来,学号 $\rightarrow$ 班号。
- 系与学生住宿:一个系的学生住在同一个宿舍区。
- 依赖:系名 $\rightarrow$ 宿舍区。
- 结合学生属性:学号 $\rightarrow$ 系名,所以存在传递依赖:学号 $\rightarrow$ 系名 $\rightarrow$ 宿舍区。
- 学生与学会:每个学生可参加若干学会,每个学会有若干学生。学生参加某学会有一个入会年份。
- 这是一个多对多 (M:N)的联系。
- 联系属性:入会年份。
第二步:构建初始关系模式
根据上述分析,我们可以初步建立以下关系模式(下划线表示主码):
- 系 (系号, 系名, 系办公室地点, 人数 )
- 注:假设系号唯一,或者系名唯一。题目中有“系名、系号”,通常选其中一个做主码,这里假设系号为主码,且系名也是唯一的(候选码)。
- 班级 (班号, 专业名, 系名, 人数, 入校年份 )
- 学生 (学号, 姓名, 出生日期, 系名, 班号, 宿舍区 )
- 学会 (学会名, 成立年份, 地点, 人数 )
- 参加 (学号, 学会名, 入会年份 )
第三步:求解最小依赖集 (Minimal Cover)
我们需要针对每个关系模式写出函数依赖集 $F$,并求其最小覆盖 $F_{min}$。
1. 关系模式:系 (Department)
- 属性: {系号, 系名, 系办公室地点, 人数}
- 依赖:
- 系号 $\rightarrow$ 系名, 系办公室地点, 人数
- (若系名也唯一) 系名 $\rightarrow$ 系号, ...
- 最小依赖集: 假设系号是主码。
- $F_{min} = { \text{系号} \rightarrow \text{系名}, \text{系号} \rightarrow \text{系办公室地点}, \text{系号} \rightarrow \text{人数} }$
- 或者合并右边:${ \text{系号} \rightarrow \text{系名, 系办公室地点, 人数} }$
2. 关系模式:班级 (Class)
- 属性: {班号, 专业名, 系名, 人数, 入校年份}
- 依赖分析:
- 班号 $\rightarrow$ 专业名, 系名, 人数, 入校年份 (班号唯一标识班级)
- 题目语义:“每个专业每年只招一个班” $\Rightarrow$ (专业名, 入校年份) $\rightarrow$ 班号
- 最小依赖集:
- $F_{min} = { \text{班号} \rightarrow \text{专业名, 系名, 人数, 入校年份}, (\text{专业名, 入校年份}) \rightarrow \text{班号} }$
- 注:这里存在两个候选码:{班号} 和 {专业名, 入校年份}。
3. 关系模式:学生 (Student)
- 属性: {学号, 姓名, 出生日期, 系名, 班号, 宿舍区}
- 依赖分析:
- 学号 $\rightarrow$ 姓名, 出生日期, 班号 (学生属于某个班)
- 班号 $\rightarrow$ 系名 (班级属于某个系)
- 系名 $\rightarrow$ 宿舍区 (题目明确:一个系的学生住在同一个宿舍区)
- 由此推导传递依赖:学号 $\rightarrow$ 班号 $\rightarrow$ 系名 $\rightarrow$ 宿舍区
- 最小依赖集:
- $F_{min} = { \text{学号} \rightarrow \text{姓名, 出生日期, 班号}, \text{班号} \rightarrow \text{系名}, \text{系名} \rightarrow \text{宿舍区} }$
- (注意:这里去掉了冗余的直接依赖,如 学号 $\rightarrow$ 系名,因为它可以通过传递得到)
4. 关系模式:学会 (Society)
- 属性: {学会名, 成立年份, 地点, 人数}
- 最小依赖集:
- $F_{min} = { \text{学会名} \rightarrow \text{成立年份, 地点, 人数} }$
5. 关系模式:参加 (Membership)
- 属性: {学号, 学会名, 入会年份}
- 依赖分析:
- (学号, 学会名) $\rightarrow$ 入会年份 (一个学生加入一个学会只有一次入会年份)
- 最小依赖集:
- $F_{min} = { (\text{学号, 学会名}) \rightarrow \text{入会年份} }$
第四步:范式分析与讨论
题目要求:指出是否存在传递函数依赖,对于函数依赖左部是多属性的情况,讨论是完全函数依赖还是部分函数依赖。
1. 关于传递函数依赖 (Transitive Dependency)
- 在“学生”关系中存在传递依赖!
- 路径:$\text{学号} \rightarrow \text{班号} \rightarrow \text{系名} \rightarrow \text{宿舍区}$
- 解释:学号决定班号,班号决定系名,系名决定宿舍区。非主属性“宿舍区”传递依赖于主码“学号”。
- 结论:目前的“学生”模式最高只满足2NF(假设没有部分依赖),但不满足3NF。为了达到3NF,需要分解。
- 分解建议:
- 学生 (学号, 姓名, 出生日期, 班号)
- 班级系 (班号, 系名)(或者利用已有的班级表)
- 系宿舍 (系名, 宿舍区)
2. 关于左部是多属性的依赖 (Multi-attribute LHS)
我们需要检查所有依赖左边有多个属性的情况:
情况 A:班级关系中的 $(\text{专业名, 入校年份}) \rightarrow \text{班号}$
- 讨论:这是完全函数依赖 (Full Functional Dependency)还是部分函数依赖 (Partial Functional Dependency)?
- 分析:
- 单独“专业名”能决定“班号”吗?不能(一个专业有很多届,多个班)。
- 单独“入校年份”能决定“班号”吗?不能(同一年有很多专业,多个班)。
- 只有两者结合才能唯一确定一个班。
- 结论:这是完全函数依赖。
情况 B:参加关系中的 $(\text{学号, 学会名}) \rightarrow \text{入会年份}$
- 讨论:
- 单独“学号”能决定“入会年份”吗?不能(一个学生参加多个学会,年份不同)。
- 单独“学会名”能决定“入会年份”吗?不能(一个学会有很多学生,入会年份不同)。
- 结论:这是完全函数依赖。
- 讨论:
第五步:指出候选码、外部码及全码
1. 候选码 (Candidate Keys)
- 系: {系号} (若系名唯一,则{系名}也是)
- 班级: {班号}, {专业名, 入校年份}
- 学生: {学号}
- 学会: {学会名}
- 参加: {学号, 学会名}
2. 外部码 (Foreign Keys)
- 班级: “系名” 引用系关系的系名/系号。
- 学生:
- “班号” 引用班级关系的班号。
- “系名” 引用系关系的系名/系号。
- 参加:
- “学号” 引用学生关系的学号。
- “学会名” 引用学会关系的学会名。
3. 是否全码存在 (All-key)
- 定义:如果关系模式的所有属性组都是候选码,则称该关系为全码。
- 分析本题:
- 在“参加”关系中,属性是 {学号, 学会名, 入会年份}。候选码是 {学号, 学会名}。因为存在非主属性“入会年份”,所以不是全码。
- 如果在某种极端设计下,比如去掉“入会年份”,只保留 {学号, 学会名} 表示成员资格,那么 {学号, 学会名} 就是全码。
- 结论:在本题给出的模式中,不存在全码。所有关系都包含非主属性(如人数、地点、入会年份等)。
最终答案总结 (可以直接抄写这部分)
1. 关系模式及最小依赖集:
- 系 (系号, 系名, 系办公室地点, 人数)
- $F_{min} = { \text{系号} \rightarrow \text{系名, 系办公室地点, 人数} }$
- 班级 (班号, 专业名, 系名, 人数, 入校年份)
- $F_{min} = { \text{班号} \rightarrow \text{专业名, 系名, 人数, 入校年份}, (\text{专业名, 入校年份}) \rightarrow \text{班号} }$
- 学生 (学号, 姓名, 出生日期, 班号, 系名, 宿舍区)
- $F_{min} = { \text{学号} \rightarrow \text{姓名, 出生日期, 班号}, \text{班号} \rightarrow \text{系名}, \text{系名} \rightarrow \text{宿舍区} }$
- (注:此处保留了传递依赖以回答后续问题,若需3NF应分解)
- 学会 (学会名, 成立年份, 地点, 人数)
- $F_{min} = { \text{学会名} \rightarrow \text{成立年份, 地点, 人数} }$
- 参加 (学号, 学会名, 入会年份)
- $F_{min} = { (\text{学号, 学会名}) \rightarrow \text{入会年份} }$
2. 依赖性质讨论:
- 传递函数依赖:在学生关系中存在传递依赖。
- $\text{学号} \rightarrow \text{班号} \rightarrow \text{系名} \rightarrow \text{宿舍区}$。即“宿舍区”传递依赖于“学号”。
- 多属性左部的依赖类型:
- 在班级关系中,$(\text{专业名, 入校年份}) \rightarrow \text{班号}$ 是完全函数依赖。因为单独的专业名或入校年份都无法决定班号。
- 在参加关系中,$(\text{学号, 学会名}) \rightarrow \text{入会年份}$ 是完全函数依赖。因为单独的学号或学会名都无法决定入会年份。
3. 码的识别:
- 候选码:
- 系:{系号}
- 班级:{班号}, {专业名, 入校年份}
- 学生:{学号}
- 学会:{学会名}
- 参加:{学号, 学会名}
- 外部码:
- 班级中的“系名”参照系的码。
- 学生中的“班号”参照班级的码,“系名”参照系的码。
- 参加中的“学号”参照学生的码,“学会名”参照学会的码。
- 全码:本题各关系模式中均不存在全码(因为每个模式都有非主属性)。