简介:《数据库系统原理与设计》第四版课后答案以doc文档形式提供,面向正在学习数据库原理课程的高校学生、准备期末考试或考研复习的读者。内容覆盖数据库系统的基本概念、组成部分、主要优点,并系统对比文件系统与数据库系统的区别和联系。文档对第1章绪论等重点章节的课后习题给出参考答案与解析,涉及数据、数据库、数据库系统、数据库管理系统等核心术语的准确含义,也对DBMS的数据定义、数据操纵、运行管理与维护功能进行说明,并附有典型应用场景的实例分析。通过对照学习,能帮助读者理顺“数据—数据库—数据库系统—DBMS”的概念层次,区分文件系统与数据库系统的适用场景,理解数据库在大型企业、电商平台等实际系统中的重要价值。资源共1个doc文件,整包约230KB,轻量易用,已有87人学习下载,很适合在课后做题后用于自测和查漏补缺,也可作为考前集中梳理知识要点的速查材料。 先说实话,我以前上学那会儿也干过到处找课后答案这种事。是不是只要拿到参考答案,这门课期末考试就能稳了?答案当然是否定的。但是反过来,如果连课后习题都啃不明白,那数据库这门课基本算是白学了。
《数据库系统原理与设计》这门课,在国内计算机相关专业里几乎是大三阶段的必修硬课。教材版本换了好几代,第四版也是目前用得最广的版本。它的课后题不是那种翻翻书就能抄出来的填空选择题,而是大量需要你动笔建模、写SQL、分析范式、推导事务调度的问题,难度梯度拉得很开。所以很多人嘴上说的“找答案”,实际上是想找一个能把自己的思路校准一遍的参照物。
这篇东西我不打算复刻任何一道原题的标准答案,而是想跟各位聊聊,当你拿到这份“课后答案”之后,到底该怎么用它,以及这门课真正要掌握的核心能力到底有哪些。毕竟答案只是结果,中间那套建模和分析的思维方式,才是能跟着你走很远的东西。
1. 内容整体设计与思路拆解
很多人觉得数据库课就是教怎么写SQL,这其实是个挺常见的误解。SQL只是这门课最表层的东西,真正硬核的部分在于“为什么这样设计”和“怎么设计才是合理的”。
第四版教材的整体脉络其实非常清晰,基本可以分成三条主线:
- 设计主线:从现实世界出发,用E-R模型把业务抽象成实体和联系,再转换成关系模式,接着通过范式理论(1NF到BCNF,甚至会提到4NF)不断优化表结构,最后落地成一组长得好看、用起来不别扭的表。
- 操作主线:围绕SQL语言展开,从数据定义(DDL)、数据操纵(DML)到视图、索引、授权控制。这部分偏实践,上手练的成本很低,装个数据库就能自己折腾。
- 系统实现主线:讲事务、并发控制、故障恢复、查询优化,还有数据库内部的存储结构。这块最抽象,也最接近“原理”两个字。很多同学挂科就挂在事务隔离级别和两段锁协议这部分。
课后习题的编排逻辑,完全是按照这三条主线来设计的。你去看那本题集配套的“参考答案”,前面几章基本是在画E-R图、转关系模式,中间章节全是SQL语句和关系代数表达式,后面章节则变成了范式判定、事务调度序列分析。
所以,使用“答案”之前,你脑子里得先有这张整体地图。否则你对着答案看了一遍,觉得自己都会了,合上书照样写不出一个满足BCNF的关系分解。
1.1 为什么课后习题比试卷更值得刷
期末考试卷子受限于考试时间和篇幅,很多知识点只能浅尝辄止。但课后题不是这样,它是教材作者对每章核心知识点的系统性检视。
以关系代数那章为例,教材课后题里会出现大量需要你手写关系代数表达式的题目。这些表达式看起来很繁琐,动不动就是“选择、投影、连接、除运算”嵌套在一起,但恰恰是这种训练能让你真正理解SQL在底层是怎么被解析执行的。等你之后做性能优化、看执行计划的时候,会发现当初刷过的关系代数并非无用武之地。
再比如范式那章,课后题会让你反复做“给定一个关系模式和函数依赖集,判断最高属于第几范式,然后分解到3NF或BCNF”。这种题目本身就是为“肌肉记忆”设计的。你做得多了,看到函数依赖就能本能地判断是否存在部分依赖、传递依赖,而不是每次都得从头翻书。这种熟练度,看答案看不出来,必须自己动手推。
1.2 参考答案的正确打开方式
我把参考答案的使用方式分成三个阶段,三个阶段的目标完全不同:
- 做题前:不看答案,合上书把题目做一遍。哪怕是瞎蒙,也要写出一个自己的版本。想不出来的题目标记出来,跳过。
- 做题后:逐题对照,重点看思路差异。不要只看结果对不对,要看答案是从什么角度切入的。比如E-R图转换关系模式,你的转换结果和参考答案不一样,不代表你错了,可能只是联系的度数处理方式不同,但你必须能解释自己为什么这么转换。
- 复盘时:把做错的题目归类,找出背后的薄弱知识点。如果错的全是范式判断,那就说明函数依赖那块根基不牢,回头重看第三章。
很多人拿到答案之后直接进入“背诵模式”,整篇背下来,考试的时候却发现题目换个马甲就不认识了。原因很简单:你背的是结果,不是推导过程。
2. 核心细节解析与实操要点
数据库这门课有个特点:概念密集,一旦前面某个概念没吃透,后面会连带崩盘。我见过太多学生,第一章关系模型没搞明白,到第三章范式直接听天书。所以下面我挑几个最关键的细节展开讲,这些也是课后题里出镜率最高的考点。
2.1 E-R图转关系模式的隐藏坑
E-R图转关系模式,看起来像是一对一、一对多、多对多的套路转换,但真正考试和做项目时,坑点全在属性归并和主键选择上。
- 一对一联系:可以把联系合并到任意一端,但实际设计时通常会看查询频率,把外键放在访问更频繁的那一侧。
- 一对多联系:外键必须放在多端,这是铁律。你要是放在一端,会产生大量冗余。
- 多对多联系:必须单独转换成一张关系表,主键通常是两端的组合键。组合键的顺序有讲究,应该把区分度高的属性放在前面,这个道理跟复合索引的最左前缀原则是相通的。
很多参考答案在转换时只给出最终的表结构,不解释为什么主键选这个而不是那个。你自己做的时候,一定要逼自己写出选主键的理由。数据库表设计的核心就是主键设计,主键选错了,后续所有查询和关联都会别扭。
另外,弱实体和ISA层次结构这两类特殊情况的转换,几乎年年都考。弱实体必须依赖强实体才能存在,所以它的主键一定包含强实体的主键;ISA层次有“把父类属性下沉到子类”和“把子类属性上提”两种策略,具体选哪种取决于查询场景。
2.2 范式判定别死记硬背
范式判定是很多人的噩梦,说到底是函数依赖的基础没打牢。
我提供一个自己给学生讲课时常说的排查思路:
- 先找出全部候选键;
- 判断是否存在非主属性对候选键的部分函数依赖,有则不满足2NF;
- 再判断是否存在非主属性对候选键的传递函数依赖,有则不满足3NF;
- 最后判断每个函数依赖的决定因素是否都是超键,存在不是超键的决定因素,则不满足BCNF。
这个流程听起来简单,但实际操作时第一个坎就会卡住很多人——候选键找不全。候选键的求法建议用“属性分类法”:只在函数依赖左边出现的属性、左右两边都出现的属性、只在右边出现的属性、没出现过的属性,把这几类先分清楚,再组合验证。这是普通教材里不太会细讲、但做题极其好用的技巧。
3NF分解和BCNF分解也有区别:BCNF分解坚持“每个函数依赖左边都是超键”这一条,分解出来可能不保持函数依赖;3NF分解则使用最小函数依赖集合并同类项,能保证无损连接且保持依赖。参考答案里通常会给出多种分解结果,你要学会判断自己的分解是否正确:无损连接用Chase算法验证,保持依赖看每个依赖是否都能由某个分解后的关系模式覆盖。
2.3 SQL题最容易丢分的地方
课后题里大量SQL语句题,很多同学觉得自己会写,但一对照答案就发现问题是“不够严谨”。
举个最简单的例子,查询“没有选修任何课程的学生”。标准答案往往用NOT EXISTS,而你写的可能是NOT IN (SELECT ...)。在选修课表这一列存在NULL值的情况下,NOT IN会直接查出空表,而NOT EXISTS不会。两者的语义在NULL面前出现了分岔,这是SQL题一个非常经典的丢分点。
再比如分组查询的HAVING和WHERE条件的区别,聚集函数能不能嵌套,GROUP BY的列是否必须出现在SELECT中(MySQL允许,但是标准SQL不允许,考试以教材为准),这些细节都是参考答案能一眼暴露出问题的地方。
我强烈建议你练习SQL题的时候,本地装一个MySQL或者PostgreSQL,实际跑一下。就拿上面那个NOT EXISTS和NOT IN的例子来说,你自己插几条含NULL的数据跑一遍,比背十遍语法都管用。数据库是门实践的学问,纯靠眼睛看是看不出感觉的。
2.4 事务与并发控制里的关键模型
到第九章第十章,课后题开始变成分析题。让你判断一个并发调度是否可串行化,让你写出两段锁协议的封锁过程,分析死锁。
这里核心要掌握几个工具:
- 冲突可串行化判定:用优先图(前驱图)。每个事务是节点,存在冲突操作就画一条边,无环则可串行化。
- 两段锁协议:分扩展阶段和收缩阶段。扩展阶段只能加锁不能解锁,收缩阶段只能解锁不能加锁。
- 隔离级别:读未提交、读已提交、可重复读、可串行化,四级隔离级别对应的并发问题(脏读、不可重复读、幻读)要能一一对上。
课后题里还有不少时间戳排序协议的习题。时间戳排序的关键就是为每个数据项维护读时间戳和写时间戳,比较事务时间戳来决定操作是否合法。做题的时候,必须一步步在纸上画出事务操作和执行时间戳的对比,粗心算错一个数,后面全盘皆输。
3. 实操过程与核心环节实现
我说点实在的,光讲理论不落地等于白讲。下面我以一个虚拟的“学生选课系统”为案例,把教材课后题里涉及的几个核心环节串起来走一遍。这套流程你在期末复习时照着做,效果会很明显。
3.1 从需求描述画出E-R模型
假设需求是这样一段话:
一个学生可以选修多门课程,每门课程可以被多个学生选修;学生选修课程会产生一个成绩;每门课程由一个老师负责授课,一个老师可以负责多门课程;老师归属于某个系。
第一步不是动笔画图,而是先圈出所有名词:学生、课程、成绩、老师、系。这些名词大概率就是实体候选。
第二步找出实体间的联系方式:学生和课程是多对多联系,成绩是选修联系的属性;课程和老师是多对一联系(按题目描述,一个老师负责多门课);老师与系之间是多对一联系。
第三步画出E-R图后,转换成关系模式:
- 学生表:学号(PK), 姓名, 系名
- 课程表:课程号(PK), 课程名, 教师工号(FK)
- 选课表:学号(FK), 课程号(FK), 成绩,主键是(学号, 课程号)
- 教师表:教师工号(PK), 姓名, 系名(FK)
这一步看起来很简单,但课后题里往往会加条件,比如“一个学生只能有一个专业”“一门课程可以有多个老师授课(教学班)”,每加一个条件,E-R图和关系模式都要跟着变。训练自己快速抓住联系的重数(1:1、1:N、M:N),是这章的核心能力。
3.2 用规范化理论优化表结构
还是上面那个选课系统,假设原表设计长这样:
选课表(学号,课程号,课程名,教师工号,教师姓名,成绩)
这个表的主键是(学号, 课程号),但课程名其实只依赖于课程号,存在部分函数依赖,所以连2NF都不满足。把选课表拆分:
- 课程表:课程号(PK),课程名,教师工号
- 选课表:学号(PK),课程号(PK),成绩
这样选课表就满足2NF了。再看课程表,教师姓名依赖于教师工号,而教师工号依赖于课程号,存在传递函数依赖,所以课程表不满足3NF。继续拆:
- 课程表:课程号(PK),课程名,教师工号(FK)
- 教师表:教师工号(PK),教师姓名
至此,每个关系模式都达到3NF。这个拆分过程看似机械,但真正动手时会发现,难点在于认清依赖关系。平时练习时,建议每拆完一次就问自己一个问题:这一步消除了哪种异常(插入异常、删除异常、更新异常)?想通了,范式理论就不再是死记硬背。
3.3 写SQL并验证执行计划
表结构定好了,开始写SQL。拿课后题里比较典型的题目来说:
查询选修了“数据库原理”课程且成绩大于90分的学生姓名。
标准答案一般长这样:
SELECT DISTINCT s.sname FROM student s JOIN sc ON s.sno = sc.sno JOIN course c ON sc.cno = c.cno WHERE c.cname = '数据库原理' AND sc.score > 90;语句本身不难,但你要是真在数据库里跑一遍,就会发现几个可以深挖的点:
- 三张表连接的顺序会对性能有影响,优化器通常会选择基数小的表作为驱动表;
DISTINCT到底需不需要,取决于成绩表里一个学生对同一门课是否可能有多条记录;- 如果学生和课程之间是M:N联系,连接查询结果集可能会因为中间表的粒度问题出现笛卡尔积式的膨胀。
查看执行计划的方式,MySQL里用EXPLAIN,PostgreSQL里用EXPLAIN ANALYZE。别嫌我啰嗦,很多学生毕业后走上开发岗,面对几百毫秒的慢查询一脸茫然,就是因为上学的时候没养成看执行计划的习惯。
3.4 分析一个并发调度
课后题里还有一类题,给你两个事务的操作序列,让你判断是否可串行化。操作题,实际操作方法如下:
假设:
T1: R(A), W(A), R(B), W(B) T2: R(A), W(A), R(B), W(B)一个调度:R1(A), R2(A), W1(A), W2(A), R1(B), W1(B), R2(B), W2(B)
画优先图,看冲突操作。R1(A) 和 W2(A) 冲突,所以有边 T1 → T2;R2(A) 和 W1(A) 也冲突,所以有边 T2 → T1。出现了环,因此这个调度不是冲突可串行化的。
这种题丢分完全是因为粗心。画前驱图时,必须逐个操作往后扫描,只标记不同事务对同一数据项的读写、写读、写写冲突。我自己做题有个习惯:先写出所有冲突对,再画图,检查环。顺序乱了就容易漏边或者多画边。
4. 常见问题与排查技巧实录
这部分是我从教学和答疑过程中整理出来的高频错题点,希望能帮你少走一些弯路。
4.1 数据字典和ER模型的混淆
不少同学在做设计题时,把数据字典的内容当作属性写进E-R图,或者反过来,在数据字典里塞了实体。其实E-R图是概念模型,强调的是实体、属性和联系;数据字典是详细设计阶段的产物,描述的是数据项的定义、类型、取值范围。课后题让你画E-R图,你就老老实实画图;让你写数据字典,再补充详细说明。混在一起只会让答案显得不专业。
4.2 视图和基本表的更新混淆
SQL题里经常出现“在视图上执行INSERT/UPDATE/DELETE是否可行”的判断题。很多人靠猜,其实规则有两步:先看视图是否可更新,再看被更新的列是否来自表达式或聚集函数。
- 带
GROUP BY、DISTINCT、聚集函数、多表连接的视图通常不可更新; - 即使视图定义满足条件,如果视图列本质上是表达式计算结果,也不能直接更新。
这类题建议背下教材里那张“可更新视图”的判定表,做题时逐条套。
4.3 索引的失效场景说不全
索引相关的题目,课后答案里往往只是简单说“可以建索引”,但实际考试会让你分析查询条件是否用到索引。有几个典型的失效场景你最好跟室友也讨论几轮:
- 对索引列使用函数,例如
WHERE YEAR(birthdate) = 2000; - 隐式类型转换导致无法走索引;
- 带头索引列不在查询条件中,比如复合索引(a,b,c),条件里只给了b和c;
- 用
LIKE '%xxx'这种以通配符开头的模糊查询。
理解这些比背答案有意义。你之后做接口性能优化,排查慢SQL,逻辑跟这是一模一样的。
4.4 候选键、主键、外键概念混为一谈
基础概念一旦混,后面全是糊涂账。候选键是“能唯一标识元组的最少属性集合”,主键只是你从所有候选键里挑出来的一个。外键则是引用其他表主键的属性。有些同学说“主键就是候选键”,严格讲不算全对,主键是候选键的子集选择。
课后题里有一类问题:给你一个关系,让你找出所有候选键,并选择一个作为主键。你找出来的候选键数量和参考答案不一致,通常是因为你漏掉了“在函数依赖里只出现在左边,或者两边都没出现”的那些属性,它们必然属于每个候选键。这是我前面已经在范式判定里强调过的方法,做题时务必先用它锁定候选键全集。
4.5 死锁和活锁的辨析
并发控制章节的最后,很多同学会把死锁和活锁搞混。简单理解:死锁是大家都在等别人释放锁,谁也别想往前走;活锁是某个事务一直拿不到锁,但别人都在正常推进。
解决死锁的手段有死锁预防、死锁检测和死锁恢复。预防靠约定锁的获取顺序;检测靠等待图,有环即死锁。活锁的解决手段相对简单:采用先来先服务或时间戳优先策略,保证排队。
课后题里如果只给一个场景,让你判断是死锁还是活锁,你要看关键线索:系统是全部卡死,还是只有某一个事务一直等待?前者偏向死锁,后者偏向活锁。
5. 复盘期末冲刺与常见问题速查
如果你现在离考试只剩一两个星期,我的建议是:别再盲目刷整套题了,搞清主次,抓重点,把脑子里的知识网络拉通。
5.1 建立章节之间的桥梁
数据库这门课最神奇的地方在于,前面学的每一章,到后面都还会回来找你的。
比如第二章的关系代数和SQL,在第九章的查询优化里会用到;第三章的函数依赖和范式,在第四章的数据库设计里是校验手段。复习的时候,最好按这个逻辑把学过的东西串一遍:
先说需求分析,用E-R图建概念模型;转成关系模型后,用范式理论检查表的水位;然后写SQL,完成增删改查;数据量大到某种程度,开始建索引;多个用户同时访问,事务并发控制接管。
这样顺下来,你会发现自己脑子里不是一团散沙。具体落实下来的做法,就是在纸上默写一遍整个数据库设计流程,然后对比教材目录查漏补缺。这种方法比看答案有用得多。
5.2 做题顺序和时间的分配建议
课后题的参考答案不是让你按顺序从头看到尾的。
- 第1遍(学完每一章):只做基础题,不做高难拓展题;
- 第2遍(期中):集中做设计类和SQL类的中等难度题;
- 第3遍(期末前):刷错题,以及那些综合性强的题目,比如“给定需求文档,从零设计数据库”,这类题目往往是一张卷子最后的大题,分值很高。
我见过很多同学把时间花在背诵关系代数各种等价变换规则上,最后还是败给了E-R图转关系模式这种基础题。基础题的分拿不到,偏题怪题做对了也难以挽回。
5.3 高频考点与问题速查表
下面这张表是我个人总结的高频考点对照,建议收藏。不是让你死背,而是做题时用来定位自己卡在哪一环:
| 章节主题 | 高频考点 | 常见丢分原因 | 自查标准 |
|---|---|---|---|
| E-R模型 | 联系的重数、属性归并、弱实体 | 不区分联系度数 | 能画出完整E-R图并给出转换理由 |
| 关系模型 | 候选键、外键、完整性约束 | 候选键找不全 | 能用属性分类法快速求候选键 |
| 关系代数 | 表达式等价变换、除运算 | 嵌套逻辑混乱 | 能解释SQL对应的关系代数表达式 |
| SQL | 多表连接、分组、子查询、NULL处理 | 在不该用IN时用IN | 能说出NOT EXISTS和NOT IN的差异 |
| 范式理论 | 2NF/3NF/BCNF判定、无损分解 | 依赖集理解不完整 | 能独立完成分解并验证无损连接和依赖保持 |
| 并发控制 | 可串行化、两段锁、时间戳、死锁 | 前驱图多画或少画边 | 能画出完整前驱图并判定有无环 |
| 查询优化 | 代数优化、物理优化、执行计划 | 理论无法联系实际操作 | 能读懂EXPLAIN输出并解释关键字含义 |
5.4 避坑指南与操作心得
根据我个人经验,有几个雷区是年年都有人踩的,单独拎出来说一下。
- 不要迷信一种分解算法:3NF分解和BCNF分解算法都要会,考试时可能指定用哪一种。算法步骤不能跳,比如求最小函数依赖集时,右边属性要先分解为单一属性,再去冗余依赖,最后去掉左侧冗余属性。少了任何一步,结果可能都不一样。
- SQL语句关键词大小写不扣分,但分号别丢:教材上的标准SQL,语句结尾都要有分号,练习时养成习惯。
- 视图是否可更新的判断别只看“单表”:哪怕视图来自单表,只要属性列表里包含表达式,更新时大概率会被拒绝。
- 并发调度的题千万别心算:在草稿纸上把时间戳数值和下标的每一步都写清楚,特别是比较时间戳大小的逻辑。心算出错率极高。
- 认真对待“简答题”:很多参考答案里的简答题是答题模板,比如“什么是数据库的完整性?它与安全性有什么区别?”这种题背下来不丢人,但更要理解底层含义:完整性是针对数据语义的正确性,安全性是针对数据访问的权限控制。两者相似但出发点完全不同。
最后再分享一个小技巧:平时刷课后题,养成“写注释”的习惯。在SQL语句旁边写上这步在逻辑上对应哪层操作,在E-R图旁边标注每个联系的最小基数和最大基数。很多人觉得这是浪费时间,但真到期末复习的时候,你会感谢这些注释。因为它们能让你更快明白自己当时为什么这么做,而不是对着一堆已经陌生的图发呆。
数据库这门课,说穿了就是一门关于“如何把现实世界的业务逻辑,变成机器能高效处理的表结构和操作序列”的学问。课后答案可以给你一个正确的终点,但从起点到终点的那条路,每一步都得自己走一遍。祝各位复习顺利,考试下笔如有神。
本文还有配套的精品资源,点击获取