📝 关系模式规范化 · 习题课

📚 第12章配套练习 ⏱️ 预计 50 分钟 📝 纯纸笔题,无上机 🎯 必考模板大全
🎯 本节练习目标
  • 能识别 4 种异常(数据冗余、插入异常、删除异常、更新异常)
  • 能判断函数依赖是 完全 / 部分 / 传递 —— 必考核心难点
  • 给一个关系,能判断它是 几范式 并说明理由
  • 把不规范的关系分解成 3NF —— 综合大题

📌 答题前先看:解题三件套

本章题目类型固定,记住下面三件套,考试就稳了:

🎯 解题三件套

① 写函数依赖集 F:根据题目语义,列出所有 X→Y

② 找主码:找出"能决定所有其他属性"的最小属性集

③ 看违反哪个范式

  • 有非原子属性 → 违反 1NF
  • 主码是组合键,有非主属性 部分依赖 → 违反 2NF
  • 有非主属性 传递依赖 → 违反 3NF
⚠️ 关键概念再强化

主属性 = 主码包含的属性;非主属性 = 不在主码里的属性

② 如果主码是 单属性,那一定满足 2NF(没法部分依赖)

③ 写主码时记得看清楚:题目通常会给出,不用猜

📝 第一部分 · 概念巩固10 分钟

先做几道概念题,把讲义里的核心概念再过一遍。

练习 1.1 ⭐ 基础 异常识别

某学校的"学生选课"表中,每条记录都同时存了"学生姓名+学号+课程名+课程号+成绩"。请判断下面 4 个场景分别属于哪种异常?

① 同一个学生选了 5 门课,姓名"张三"在表里出现了 5 次

② 某老师新开了一门"数据库"课程,但还没人选,无法录入这门课

③ "数学"课程的所有选课记录被删掉后,"数学"这个课程也彻底消失了

④ 学生张三改名为张三丰,要把表里所有他的记录都改一遍

📖 查看答案

① → 数据冗余(同一信息存了多次)

② → 插入异常(应该存在但插不进去)

③ → 删除异常(删除时连带删除了不该删的信息)

④ → 更新异常(一处修改要改多处)

📌 速记:"存得多、加不进、删错了、改不全"

练习 1.2 ⭐ 基础 函数依赖概念

关于"学号 → 姓名"这个函数依赖,下列说法 错误 的是?

📖 查看答案

✅ 答案:C 错误

函数依赖是 "由左决定右" 的单向关系。"学号→姓名"只说明知道学号能查到姓名,但 反过来不一定成立(因为可以同名)。

D 是对的:函数依赖左边只有一个属性时,一定是完全函数依赖(没法再"少一个"了)。

练习 1.3 ⭐⭐ 中等 三种依赖辨识 · 必考

下列关于函数依赖的描述,哪一组对应是正确 的?

📖 查看答案

✅ 答案:B

三种依赖的判断口诀:

完全 = 左边一个都不能少(少一个就决定不了右边)

部分 = 左边的一部分就够了(说明有冗余属性)

传递 = 中间通过另一个属性"中转"

练习 1.4 ⭐⭐ 中等 范式定义

下列关于范式的说法,正确 的是?

📖 查看答案

✅ 答案:C

逐个分析:

A 错:范式是层层递进的,3NF 必然先满足 2NF,2NF 必然先满足 1NF。

B 错:消除传递依赖是 3NF 的要求。2NF 是消除部分依赖。

C 对:3NF 的定义就是这个。

D 错:范式越高,表越多、查询时需要的 JOIN 越多,性能反而可能下降。规范化要在"安全"和"性能"之间权衡。

练习 1.5 ⭐ 基础 范式辨别

三大范式分别要求消除什么?请连线匹配。

① 1NF

② 2NF

③ 3NF

选项:A. 部分函数依赖 | B. 非原子属性 | C. 传递函数依赖

📖 查看答案

① 1NF → B(消除非原子属性,每个值都是原子的)

② 2NF → A(消除非主属性对主码的部分依赖)

③ 3NF → C(消除非主属性对主码的传递依赖)

🔍 第二部分 · 函数依赖判断15 分钟 · 必考

本部分是 必考核心难点。给一个关系,要能 ① 写出函数依赖集 F,② 找出主码,③ 判断每个依赖是完全/部分/传递。

练习 2.1 ⭐⭐ 中等 写出函数依赖集

商品库存关系

商品库存: (商品编号, 商品名称, 类别, 生产厂家, 库存量, 经销商编号, 经销商名称, 经销商联系方式)

已知:① 一个商品有一个商品编号、一个名称、一个类别、一个厂家、一个库存量;② 一个商品由一个经销商代销;③ 经销商编号唯一确定经销商名称和联系方式。

请回答:① 主码是什么?② 写出所有函数依赖。

📖 查看答案

主码 = 商品编号(唯一确定一行)

② 函数依赖集 F:

商品编号决定的:

商品编号 → 商品名称, 类别, 生产厂家, 库存量, 经销商编号

经销商编号决定的:

经销商编号 → 经销商名称, 经销商联系方式

合并写法:

F = { 商品编号→商品名称, 商品编号→类别, 商品编号→生产厂家, 商品编号→库存量, 商品编号→经销商编号, 经销商编号→经销商名称, 经销商编号→经销商联系方式 }

💡 思考:这里存在传递依赖吗?
商品编号 → 经销商编号 → 经销商名称,所以 商品编号 → 经销商名称 是传递依赖。

练习 2.2 ⭐⭐ 必考 辨别完全/部分依赖

在选课关系 SC(学号, 课程号, 课程名, 学分, 成绩) 中,主码是 (学号, 课程号)。请判断以下各依赖关系,哪些是完全依赖,哪些是部分依赖

  1. (学号, 课程号) → 成绩
  2. (学号, 课程号) → 课程名
  3. (学号, 课程号) → 学分
📖 查看答案与解题步骤

解题方法:检查左边的每个子集能否决定右边。能 → 部分依赖;不能 → 完全依赖。

① (学号, 课程号) → 成绩

❓ 只给学号能确定成绩吗?不能(一个学生有多门课的成绩)
❓ 只给课程号能确定成绩吗?不能(一门课有多个学生的成绩)
✅ 必须两个都给 → 完全函数依赖

② (学号, 课程号) → 课程名

❓ 只给课程号能确定课程名吗?能!(每门课只有一个名字)
✅ 不需要学号 → 部分函数依赖 ❌

③ (学号, 课程号) → 学分

❓ 只给课程号能确定学分吗?能!(每门课的学分是固定的)
✅ 不需要学号 → 部分函数依赖 ❌

📝 结论:课程名、学分 都是部分依赖于主码 —— 这违反 2NF!

练习 2.3 ⭐⭐ 必考 辨别传递依赖

在员工关系 EMP(员工编号, 姓名, 部门号, 部门名称, 部门经理) 中,主码是员工编号。已知函数依赖集:

F = { 员工编号 → 姓名, 员工编号 → 部门号, 部门号 → 部门名称, 部门号 → 部门经理 }

请回答:

  1. 找出所有 传递函数依赖(写出完整的传递链)
  2. 这个关系满足 3NF 吗?为什么?
📖 查看答案与解题步骤

① 找传递依赖:找形如 A→B→C 的链。

传递链 1

员工编号 → 部门号 → 部门名称
所以:员工编号 → 部门名称 是传递依赖(中间属性是部门号)

传递链 2

员工编号 → 部门号 → 部门经理
所以:员工编号 → 部门经理 是传递依赖

② 是否满足 3NF?

❌ 不满足 3NF,因为存在非主属性(部门名称、部门经理)对主码的传递依赖

💡 解决办法:把部门信息单独拆出来,分解成:

EMP(员工编号, 姓名, 部门号)
DEPT(部门号, 部门名称, 部门经理)

📊 第三部分 · 范式判断15 分钟 · 必考

本部分是必考的 "判断这是几范式" 题型。解题三步走:1NF? → 2NF? → 3NF?

练习 3.1 ⭐⭐ 中等 最高范式

关系 R(A, B, C, D),主码为 A,函数依赖集 F = {A→B, A→C, A→D}
这个关系最高满足第几范式?

📖 查看答案与解题步骤

✅ 答案:C · 3NF

第一步:1NF?

所有属性都是原子值,✓ 满足

第二步:2NF?

主码 A 是 单属性,自动满足 2NF(没法部分依赖)。✓

第三步:3NF?

所有依赖都是 A→某属性,没有 A→X→Y 这样的传递链。✓ 满足 3NF

💡 关键点:当主码是单属性时,2NF 自动满足。再看是否有传递依赖即可判断 3NF。

练习 3.2 ⭐⭐ 必考 最高范式

关系 R(A, B, C, D),主码为 A,函数依赖集 F = {A→B, B→C, A→D}
这个关系最高满足第几范式?

📖 查看答案与解题步骤

✅ 答案:B · 2NF

第一步:1NF?

原子属性,✓ 满足

第二步:2NF?

主码 A 是单属性,✓ 自动满足 2NF

第三步:3NF?

看 F:A→B,B→C,存在传递链 A→B→C,所以 A→C 是传递依赖
❌ 违反 3NF

📝 所以这个关系最高只能满足 2NF

💡 对比 3.1 题:3.1 题 F = {A→B, A→C, A→D},B 和 C 都直接由 A 决定,没有传递;3.2 题 F = {A→B, B→C, A→D},C 是由 B 决定的,存在传递。

练习 3.3 ⭐⭐ 必考 组合主码的判断

关系 R(A, B, C, D),主码为 (A, B),函数依赖集 F = {(A,B)→C, A→D}
这个关系最高满足第几范式?

📖 查看答案与解题步骤

✅ 答案:A · 1NF

第一步:1NF?

原子属性,✓ 满足

第二步:2NF?

主码是 组合键 (A, B),必须检查每个非主属性:

① C:(A,B)→C,A 和 B 都需要才能决定 C → 完全依赖 ✓

② D:A→D,只用 A 就能决定 D,不需要 B部分依赖 ❌

❌ 违反 2NF!

📝 既然违反 2NF,最高就只能是 1NF

💡 这就是"组合主码 + 部分依赖" 的典型场景。

练习 3.4 ⭐⭐⭐ 进阶 综合判断

某图书借阅系统的关系:

借阅记录: (读者编号, 读者姓名, 图书编号, 图书名称, 借阅日期) 主码:(读者编号, 图书编号)

请回答:① 写出函数依赖集 F;② 这个关系最高满足第几范式?

📖 查看答案与解题步骤

① 写出函数依赖集 F:

F = {
  读者编号 → 读者姓名,
  图书编号 → 图书名称,
  (读者编号, 图书编号) → 借阅日期
}

② 判断范式:

第一步:1NF?

原子属性,✓ 满足

第二步:2NF?

主码 (读者编号, 图书编号),检查非主属性:

① 读者姓名:只依赖读者编号 → 部分依赖 ❌

② 图书名称:只依赖图书编号 → 部分依赖 ❌

③ 借阅日期:完全依赖于 (读者编号, 图书编号) ✓

❌ 违反 2NF

📝 答案:最高只满足 1NF

💡 想升级到 3NF,需要拆成 3 张表 —— 这就是下一部分的内容!

🔧 第四部分 · 模式分解(综合大题)15 分钟 · 必考

本部分是 综合大题,把整章知识连起来用。给一个不规范的关系,要 分解成 3NF 的多张表

📋 模式分解的标准答题模板

🎯 分解三步走

① 写出原关系的函数依赖集 F

② 找出违反范式的依赖(部分依赖、传递依赖)

③ "一事一地"原则拆表:每张表只描述一件事

⚠️ 拆表小技巧

遇到部分依赖(左边是组合键的子集 → 右边):把"子集 + 它能决定的属性"单独成表。

遇到传递依赖(A→B→C):把"B + C"单独成表,原表保留 A→B 即可。

练习 4.1 ⭐⭐ 必考 标准模式分解题

把练习 3.4 的"借阅记录"关系分解成满足 3NF 的多张表。

原始关系: 借阅记录(读者编号, 读者姓名, 图书编号, 图书名称, 借阅日期) 主码:(读者编号, 图书编号)
📖 查看答案与解题步骤

解题过程:

第一步:写出函数依赖集 F

F = {
  读者编号 → 读者姓名,
  图书编号 → 图书名称,
  (读者编号, 图书编号) → 借阅日期
}

第二步:识别问题

读者姓名和图书名称都是部分依赖于主码(违反 2NF)。

第三步:按"一事一地"原则拆分

关系中其实涉及 三件事:读者信息、图书信息、借阅这件事。每件事一张表:

📦 最终分解结果(满足 3NF)
读者(读者编号, 读者姓名) · 主码 读者编号
图书(图书编号, 图书名称) · 主码 图书编号
借阅(读者编号, 图书编号, 借阅日期) · 主码 (读者编号, 图书编号)

💡 检验:每张表的主码都能决定其他所有属性,没有部分依赖也没有传递依赖 → ✓ 都满足 3NF。

练习 4.2 ⭐⭐ 必考 含传递依赖的分解

员工管理 关系:

原始关系: 员工(员工编号, 员工姓名, 部门号, 部门名称, 部门经理) 主码:员工编号

已知:① 员工编号唯一确定员工姓名和所在部门号;② 部门号唯一确定部门名称和部门经理。

请把这个关系分解成 3NF

📖 查看答案与解题步骤
第一步:函数依赖集 F

F = {
  员工编号 → 员工姓名,
  员工编号 → 部门号,
  部门号 → 部门名称,
  部门号 → 部门经理
}

第二步:识别问题

主码是单属性 → 自动满足 2NF ✓

但存在传递依赖:

① 员工编号 → 部门号 → 部门名称(传递)

② 员工编号 → 部门号 → 部门经理(传递)

❌ 违反 3NF

第三步:切断传递链,拆出"部门"独立成表
📦 最终分解结果(满足 3NF)
员工(员工编号, 员工姓名, 部门号) · 主码 员工编号
部门(部门号, 部门名称, 部门经理) · 主码 部门号

💡 检验:

① 员工表:主码员工编号 → 员工姓名、部门号,都是直接依赖。✓

② 部门表:主码部门号 → 部门名称、部门经理,都是直接依赖。✓

练习 4.3 ⭐⭐⭐ 进阶 综合大题

某商品库存关系(练习 2.1 的扩展):

原始关系: 商品库存(商品编号, 商品名称, 类别, 生产厂家, 库存量, 经销商编号, 经销商名称, 经销商联系方式) 主码:商品编号

请:① 分析现有关系的范式等级;② 进行模式分解使其满足 3NF。

📖 查看答案与解题步骤
第一步:函数依赖集 F

F = {
  商品编号 → 商品名称, 类别, 生产厂家, 库存量, 经销商编号,
  经销商编号 → 经销商名称, 经销商联系方式
}

第二步:当前范式等级分析

① 1NF?所有属性原子,✓ 满足

② 2NF?主码是单属性商品编号,自动满足 ✓

③ 3NF?检查传递依赖:
商品编号 → 经销商编号 → 经销商名称 ❌(传递)
商品编号 → 经销商编号 → 经销商联系方式 ❌(传递)

📝 当前最高满足 2NF,违反 3NF

第三步:分解

切断传递链:把"经销商"信息独立成表。

📦 最终分解结果(满足 3NF)
商品(商品编号, 商品名称, 类别, 生产厂家, 库存量, 经销商编号) · 主码 商品编号
经销商(经销商编号, 经销商名称, 经销商联系方式) · 主码 经销商编号

💡 检验:

① 商品表:主码 → 其他属性,都是直接依赖(包括外键经销商编号也是直接依赖)。✓

② 经销商表:主码 → 名称、联系方式,直接依赖。✓

📌 商品表里保留 经销商编号 作为外键,用来连接两张表。

练习 4.4 ⭐⭐⭐ 进阶 同时含部分+传递依赖

课程教学 关系,描述了"哪个学生选了哪门课、由哪个老师教、老师所在的办公室":

原始关系: 课程教学(学号, 学生姓名, 课程号, 课程名, 教师号, 教师姓名, 办公室, 成绩) 主码:(学号, 课程号)

已知:① 一门课由一个老师教(教师号唯一确定);② 一个老师在一个办公室。

请把这个关系分解成 3NF

📖 查看答案与解题步骤
第一步:函数依赖集 F

F = {
  学号 → 学生姓名,
  课程号 → 课程名, 教师号,
  教师号 → 教师姓名, 办公室,
  (学号, 课程号) → 成绩
}

第二步:分析问题

① 部分依赖:

  学生姓名只依赖学号(违反 2NF)

  课程名、教师号只依赖课程号(违反 2NF)

② 传递依赖:

  课程号 → 教师号 → 教师姓名(违反 3NF)

  课程号 → 教师号 → 办公室(违反 3NF)

第三步:分解

识别出 4 件事:学生、课程、教师、选课。每件事一张表:

📦 最终分解结果(满足 3NF)
学生(学号, 学生姓名) · 主码 学号
课程(课程号, 课程名, 教师号) · 主码 课程号
教师(教师号, 教师姓名, 办公室) · 主码 教师号
选课(学号, 课程号, 成绩) · 主码 (学号, 课程号)

💡 检验所有 4 张表:

① 学生表:主码单属性 ✓ 直接依赖 ✓

② 课程表:主码单属性 ✓ 没有传递(教师号是外键,已不在传递链中)✓

③ 教师表:主码单属性 ✓ 直接依赖 ✓

④ 选课表:主码组合键,唯一非主属性"成绩"完全依赖 ✓

📝 复习重点回顾

通过本次练习,你应该已经:

⭐ 期末考点排行榜

按照在历年试卷中出现的频率排序:

  1. 模式分解题:给关系,分解成 3NF(综合大题,分值最高)
  2. 判断函数依赖类型:选择题/填空题
  3. 判断范式等级:选择题
  4. 4 种异常识别:选择题/简答题
  5. 函数依赖集的写法:综合题中的一部分
💡 备考建议

第 12 章是 纯理论 章节,练习时多用纸笔反复推演。考前一周:

① 把"三种依赖判断口诀"和"三大范式定义"背熟

② 找 3-5 道模式分解题,反复练习直到不看答案能写出全过程

③ 注意区分"主码是单属性"和"主码是组合键"的判断差异