
作为一名去年刚带完一届学生、又帮好几批考研党做过数据库系统概论答疑的老学长我今天想认真聊聊王珊老师这本《数据库系统概论》第五版的课后习题。说实话这本书在计算机专业教材里的地位不用我多吹国内绝大多数高校的数据库课程、考研专业课用的都是它。而我见过太多人栽在同一个误区上课后题看了一眼觉得答案不就在书里吗结果一到期末考试、考研真题才发现自己连第三范式到底怎么判断这种最基础的题都没真正吃透。这篇我把自己带学生刷题、自己复习考研时踩过的坑、总结过的方法论全盘托出。我不会只给你贴一份现成答案我要讲清楚每类习题背后的考察逻辑、做题思路、以及那些书里没写但考试必考的细节。无论你是期末突击、考研二战还是工作后想补数据库理论底子这篇应该都能帮你省下大量自己摸索的时间。1. 这本书为什么值得反复啃很多人问过我一个挺扎心的问题数据库这门课我SQL写得很溜为什么期末考还是挂答案其实很残酷因为考试考的不是你会不会写SQL而是你能不能讲清楚SQL背后的那张关系代数网、那套完整性约束设计逻辑、以及事务并发控制里的那些锁协议。《数据库系统概论》第五版的核心价值恰恰在于它把数据库从会用提升到了懂原理的层次。它整本书的结构是典型的分层递进先讲数据模型和关系数据库基础再进SQL语言和数据库安全完整性然后是关系数据理论函数依赖和范式和数据库设计最后是数据库编程、查询优化、恢复技术和并发控制。每章后面配套的习题就是用来逼你完成从看懂到能讲这个过程的最好工具。还有一个现实因素考研。计算机统考408的数据库部分或者各校自主命题的数据库专业课基本都以这本书为蓝本。我当年考研时把课后题刷了三遍每一遍都有新发现。第一遍是期末水平第二遍才发现有些题其实在考为什么第三遍才真正能把不同章节的知识串成一张网。这本书的习题设计很克制不靠偏题怪题取胜靠的就是把核心概念翻来覆去地考察。另外说一句很多人纠结第五版和第六版的差别。第六版我翻过主要是在部分章节做了精简、更新了部分案例和数据但核心框架并没有大改。如果你手头是第五版完全不用焦虑课后题的题型和知识点覆盖度依然非常能打。如果你用的是第六版其实和第五版的核心考点基本重合绝大多数经典习题可以通用参考思路只是在章节编号和部分表述上略有差异。2. 刷题前必须搞清楚的一件事答案不重要考察点才重要2.1 课后习题的三种典型类型我观察下来这本书的课后题基本可以分成三个类型对待方式完全不同。第一种是概念辨析题。比如简述数据库系统的特点、解释数据独立性的含义这类题看着简单却是最容易被忽视的。很多同学背书式地抄一遍答案合上书本又是一片空白。我的建议是这类题一定要用自己的话复述最好能画一张图或者举一个生活中的例子。比如数据独立性你光背物理独立性和逻辑独立性不够你得能讲清楚我把表的某一列从INT改成BIGINT应用程序为什么不用改这背后的逻辑独立性体现在哪里能举出例子才算真正掌握。第二种是设计分析题。比如关系模式的函数依赖判断、候选键求解、范式级别的判断、E-R图设计。这类题是考试的重灾区也是这本书习题的灵魂。它们的共同特点是有确定的方法论但需要你按步骤操作一步错步步错。对付这类题我建议把解题过程当作算法来对待每一步都留下书写痕迹方便回查。第三种是SQL/关系代数操作题。包括用SQL语句实现查询、用关系代数表达式表达查询、以及后面的存储过程、触发器、查询优化等内容。这类题考察的是知识转化能力。很多同学上课听懂了一到自己写SQL就卡壳。破解之道只有一个亲手在真实数据库里跑一遍。光在纸上写你永远不知道自己写的SQL在语法层面会有多离谱。2.2 高效刷题的三轮法我带学生复习时一直建议大家用三轮刷题法效果非常显著。第一轮随章同步刷。学完一章做一章不限时间允许翻书。此时的核心目标是理解——搞清楚每道题在问什么、对应教材里的哪个知识点、标准答案的逻辑链条是什么。这一轮不要求快但要求细。第二轮整书综合刷。整本书学完后从头开始不翻书地刷第二遍。此时的目标是记忆提取。你会发现第一遍觉得会的题目第二遍可能写不完整。这非常正常不要气馁。把写不出来的题目标记出来这是你的知识薄弱点清单。第三轮重点突破刷。距离考试前专门针对标记的薄弱点和每章的重难点范式判断、并发控制、查询优化进行第三轮刷题。这一轮的目标是条件反射。要求看到题目就能立刻反应出解题思路和易错点。这三轮下来花的遍数不多但每一遍的目的都不一样。比起盲目刷十遍效果要好得多。3. 分章节核心知识点与习题思路深度拆解3.1 关系数据理论函数依赖与范式判断这是整本书最容易让人一看就会一做就废的章节也是我想重点讲的。先说函数依赖。考试最喜欢考察的是完全函数依赖、部分函数依赖和传递函数依赖的辨析。很多同学分不清楚的关键在于不理解依赖是属性与属性之间的一种约束关系。我上课时用一个学生选课的例子来讲在选课表(学号, 课程号, 成绩)中成绩完全函数依赖于(学号, 课程号)但如果这个表里还有班主任姓名而班主任姓名只依赖学号那它就是部分函数依赖如果班主任姓名依赖系别、系别依赖学号那么班主任姓名对学号就是传递函数依赖。这里有个小技巧判断部分还是完全关键看决定因素能不能缩小判断是否传递关键看是否存在一个中介属性。这两个点成了范式级别的判断基本就能拿下一半。再说候选键求解。这是很多题的起点因为判断范式级别前你得先找出主属性。求候选键有一个通用算法我强烈建议大家不要凭空肉眼观察而是按步骤来第一步把所有属性分成四类只在函数依赖左边出现的属性L类、只在右边出现的属性R类、两边都出现的属性LR类、两边都没出现的属性N类。第二步L类属性和N类属性一定要包含在候选键中。第三步如果这些属性的闭包能覆盖全部属性候选键就找到了不行的话再把LR类属性逐个组合进去试闭包。说实话这个方法虽然看起来繁琐但比肉眼观察可靠得多。我在考场上看到过太多人因为肉眼观察漏掉候选属性而出错。范式判断的套路就更固定了。先判断有没有非主属性对码的部分依赖有就只达到1NF去掉部分依赖后再判断有没有非主属性对码的传递依赖有就是2NF再去掉传递依赖后判断有没有非主属性完全依赖于码的每一个候选键即满足3NF最后看是否存在主属性对码的部分依赖或传递依赖判断是否达到BCNF。这个流程像算法一样明确照着走基本不丢分。3.2 关系数据理论进阶模式分解的两种算法模式分解这部分很多同学只记住了无损连接和保持依赖这两个名词但真让写步骤就懵了。第五版教材里重点讲了两种分解算法分解为3NF的合成算法和分解为BCNF的分解算法。3NF合成算法的关键是先求函数依赖集的最小函数依赖集最小覆盖然后按每个函数依赖的左边分组每个组形成一个关系模式。这里有个特别容易踩的坑如果最小覆盖里没有任何一个关系模式包含原关系模式的候选键需要单独加一个包含候选键的偏关系模式。这个细节很多教材答案里都没写但考试一旦考到就是拉开差距的地方。BCNF分解法则不同它是自顶向下的。从原关系模式开始检查是否存在非平凡函数依赖导致BCNF违反如果违反就拆开递归处理直到所有子模式都满足BCNF。这里要注意BCNF分解可以保证无损连接但不一定保持函数依赖。题目如果问你能否保持依赖答案不一定需要具体分析。这里也顺带回答一个我经常被问的问题3NF和BCNF到底选哪个实际工程中3NF已经覆盖了绝大多数场景它同时保证无损连接和保持依赖。而BCNF虽然在消除冗余上更彻底但可能因为不保持依赖而牺牲某些完整性约束的自动维护能力。考试中如果题目不做要求默认3NF性价比最高。3.3 数据库设计E-R图到关系模式的转换细节这一章的课后题主要围绕数据库设计的六个阶段展开需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库实施、数据库运行和维护其中概念结构设计里的E-R图几乎是必考题逻辑结构设计里的E-R图转关系模式更是重点中的重点。E-R图转关系模式我总结了一个口诀实体转成表联系看类型。一对一的联系可以并入任意一端的实体表也可以独立成表一对多的联系并入多端实体表外键指向一端主键多对多的联系必须独立成表然后放入双方实体的主键作为联合主键同时在此外键上建立关联。这个口诀确实能解决大部分小题但真正需要警惕的有两点。第一点多元联系三个及以上实体参与的练习的处理。这时是否可以并入某一端实体题型不再那么简单。教材里通常建议多元联系一般需要独立成表把参与联系的各实体主键作为外键。具体是否合并看题目提示和语义需求。做题时先把题目中的语义完全读懂再决定是采用独立表还直接并入某实体表很多同学在这一步丢分是因为没读懂题意就套口诀。第二点属性的归属问题。如果一个属性同时依赖于多个实体那么它应该归属于联系而不是其中一个实体。例如用量这个属性既依赖于产品又依赖于订单那它就是订单-产品的联系属性应该被放在联系转换出的关系表交叉表或联系表中而不是产品的属性。这个点看起来简单但在复杂E-R图里很容易被忽略。另外提醒一句第四节物理结构设计里关于索引选择和存储结构设计的习题容易被人忽视。这部分虽然理论性偏强但期末考试偶尔会出选择或简答比如什么时候应该建索引什么时候不应该答案核心就几条频繁出现在查询条件、连接条件、排序分组中的属性适合建索引频繁更新的属性、数据量很小的表、取值重复率很高的属性不适合建索引。背下来有用。3.4 SQL与关系代数的互相转化思路很多学校的考试喜欢出一个题给一个查询需求既用关系代数表达又用SQL表达或者反过来。这背后考察的是同一种查询能力。关系代数的核心操作其实不多选择σ、投影π、连接⋈、并∪、差-、笛卡尔积×。难点在于如何用这些操作组合出复杂的查询语义。这里有一个核心思维转换SQL的WHERE条件、JOIN、SELECT列分别对应关系代数的选择、连接、投影。当你拿到一个查询需求时先思考它的筛选条件和连接关系是什么再考虑要投影哪些列。举个具体例子查询选修了课程名为数据库的所有学生姓名。这个查询涉及三张表学生(Student)、选课(SC)、课程(Course)。SQL写起来比较直接SELECT Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno (SELECT Cno FROM Course WHERE Cname数据库))。而关系代数呢就是先做Student和SC做自然连接配合Course出来一张大表再做选择σ Cname数据库最后做投影π Sname。对比一下你就能发现关系代数其实更像管道SQL更像人类语言。理解了这个对应关系你就不会被这类题难住了。还有一类SQL题是嵌套查询改成连接查询。这类题的技巧是IN子查询通常可以改写成JOIN。比如上面的例子可以改写为SELECT Sname FROM Student JOIN SC ON Student.SnoSC.Sno JOIN Course ON SC.CnoCourse.Cno WHERE Cname数据库。改写的关键是找到子查询和父查询之间的关联列。这类题考试很喜欢出因为能同时考你对SQL语义的理解和等价改写能力。4. 从课后习题到真实数据库动手实操才是硬道理4.1 在真实环境里复现课后习题我建议每一位正在学这本书的读者都去装一个MySQL或者PostgreSQL把课后习题里的建表、查询、视图、索引、触发器在真实环境里跑一遍。这一步做好能解决你至少一半的看起来懂了但不会写问题。为什么因为数据库理论教材里的SQL习题通常都是高度理想化的真实环境会让你面对各种脏问题字段类型到底选INT还是VARCHAR、外键要不要加ON DELETE CASCA DE、插入数据时主键冲突了怎么办、NULL值参与运算结果竟然不是FALSE……这些问题课本不会明确讲但你手一摸数据库就全懂了。选型方面如果只是学习用MySQL 8.0或者PostgreSQL 15都可以。我个人更推荐PostgreSQL因为它在标准SQL遵循度上更好教材里的很多写法可以原样运行。但如果你学校的课程实验环境是MySQL那跟着学校走也没问题SQL基础一致能进入实战目标才算达到。安装和学习过程中也教大家一个很方便的方式就是随便找一些在线SQL模拟环境的网站直接测。因为本地装环境对一些新手确实有门槛需要装服务、调端口、设置用户在线环境打开浏览器就能跑SQL上手成本极低。等你在在线环境里把基础SQL练熟了再回到本地装MySQL/PostgreSQL问题就小很多。4.2 一个典型的实操案例用课后题里的SPJ数据库跑查询我拿书中经典的SPJ例子供应商、零件、工程项目、供应情况来做个简化示范。先把表建出来。这里我就直接给一段可用的DDL脚本你在MySQL或PostgreSQL里都能跑。注意下方是MySQL的写法PostgreSQL需要把 VARCHAR 换成 TEXT 或者同样用 VARCHAR 也兼容建议保持一致。CREATE DATABASE spj_demo; USE spj_demo; CREATE TABLE S ( Sno CHAR(2) PRIMARY KEY, Sname VARCHAR(20), Status INT, City VARCHAR(20) ); CREATE TABLE P ( Pno CHAR(2) PRIMARY KEY, Pname VARCHAR(20), Color VARCHAR(10), Weight INT ); CREATE TABLE J ( Jno CHAR(2) PRIMARY KEY, Jname VARCHAR(20), City VARCHAR(20) ); CREATE TABLE SPJ ( Sno CHAR(2), Pno CHAR(2), Jno CHAR(2), Qty INT, PRIMARY KEY (Sno, Pno, Jno), FOREIGN KEY (Sno) REFERENCES S(Sno), FOREIGN KEY (Pno) REFERENCES P(Pno), FOREIGN KEY (Jno) REFERENCES J(Jno) );建完表后随便插入几行测试数据然后试着跑课后习题里的那一串查询比如查询使用供应商S1所供应的零件的工程名称。你可以先自己写写不出就参考答案的SQL看完答案别急着切走把答案敲进数据库里执行一遍。这一遍执行比你抄十遍答案都管用。这类实操的意义不只在于验证答案正不正确更在于你会在执行过程中记住一些意外的细节。比如我第一次在MySQL里敲课后题时有一个子查询的写法数据库直接报了语法错误我才意识到不同数据库对别名的处理AS 能不能省略竟然不一样。这种细节你不实操永远不会知道。4.3 用LeetCode数据库题检验学习效果如果觉得课后习题不够实战我非常推荐大家去刷LeetCode的数据库题库。很多人听到LeetCode第一反应是算法题其实它的数据库题Database板块设计得很精巧从简单的SELECT到复杂的窗口函数、连续问题、树形查询都有。刷LeetCode数据库题对我帮助最大的不是学会了某个函数而是锻炼了把需求翻译成SQL的能力。这种能力恰好也是课后习题里最难培养的——课后习题的SQL题往往单表、简单查询居多但真实的考试和工作中多表关联、子查询、分组过滤才是常态。学习节奏上建议课后题LeetCode交叉进行。学完书上某章的SQL部分后去LeetCode刷5道左右的数据库题学完范式那章后去LeetCode找找相关的范式设计题虽然偏少但也有一小部分。这种理论实践的节奏整体来说功效比非常高。5. 常见问题与避坑实录5.1 课后答案到底去哪找才靠谱我深知很多读者打开这篇博文的第一个念头是什么你直接告诉我标准答案在哪里看。我也不卖关子直接说结论。第一最靠谱的是教材配套的教辅资料。人大金仓和高等教育出版社都出过配套的习题解答这是官方且质量最高的答案来源。第二很多高校的数据库课程网站或教学平台会放出课后习题答案你可以搜学校名数据库系统概论课后答案大概率能找到。第三CSDN、GitHub、知乎上也有很多热心人整理的答案仓库。但这里我非常不建议直接照抄这类答案因为里面确实存在错误而且不同的人整理时反而容易新增错误。自己先做做完再对照这样既不被误导也能真正检验自己的水平。我自己的习惯是先用纸质答案或官方教辅做一遍遇到争议题再在CSDN或知乎搜其他人的思路。多方对照之后你对这道题的理解才会立体。5.2 为什么我建议你千万别背答案我有个印象特别深的案例。曾经有个学生期末前找到我说自己把课后习题答案背得滚瓜烂熟结果一考试遇到一道很简单的E-R图转关系模式题只是换了个场景从学校选课换成了快递物流他就彻底懵了。这种情况太典型了。数据库这门课的特点是核心概念少但应用场景千变万化。你背下来的具体答案换个包装就不认识了。但如果你掌握的是思路比如多对多联系独立成表、外键放在多的一端那么无论场景怎么换你都能应对自如。所以我的建议特别简单做课后题时答案只是参考一定要看你自己的推导过程。如果过程和标准答案不一样但结果一样那也是一件了不起的事情说明你是真的理解了这个知识点。如果过程一样但中间某一步不理解务必回到教材里看原理不要跳过。5.3 期末、考研的复习顺序建议到了复习冲刺阶段时间紧任务重不建议一页页从头翻教材。我的推荐顺序是这样的第一优先用课后题当目录做一次知识扫描。只看每一章的课后题回想这道题对应什么知识点如果你看到题目完全想不起来考的是什么马上标记回教材找对应章节补这块知识。第二优先集中攻克计算和分析型题目包括范式判断、候选键求解、模式分解、事务并发调度、查询优化。这些是做题性价比最高的题型短时间冲刺提升快。第三优先SQL和关系代数的操作题用电脑实操代替纸面阅读保持手感和速度。至于概念型简答题碎片时间背一背即可不用花大块时间。我还想特别提醒考研的同学一句很多学校的408或自主命题专业课数据库部分的题目难度其实并不高但特别重视基础概念的理解深度。你会发现真题里有很多就是对课后习题的改编换个数字、换个实体名称考察逻辑完全一样。所以真题与课后题结合起来复习是效率最高的路径。5.4 一道容易被误解的经典题第四范式和多值依赖很多同学刷到第五版第十章或对应章节时会遇到第四范式4NF的相关内容。这一部分教材讲得相对简略有些老师甚至直接跳过。但从考研真题反馈来看个别学校偶尔会出选择或判断小题多值依赖和函数依赖的区别以及4NF的定义。我建议最起码要记住两个要点第一多值依赖的定义是一个决定因素可以决定一组取值最经典的例子是课程CTeacher对应多个老师但同时课程也对应多个教材。在这个二维表C, T, B里C决定T的集合也决定B的集合T和B互相独立。这种取值独立就导致了大量冗余。第二4NF要求关系模式属于BCNF并且消除所有的非平凡多值依赖。这个知识点不需要你像3NF、BCNF那样熟练运用分解算法但概念一定要能辨析清楚。5.5 事务、并发控制与恢复大题高发区考试的最后一道大题通常落在事务调度、封锁协议或故障恢复上这是很多同学觉得最难的部分其实也是套路最固定的部分。可串行化调度判断是高频考点。先记住冲突操作的概念两个不同事务的读写或写写操作作用在同一数据项上且至少有一个是写操作。然后学会用优先图判断冲突可串行化将事务作为节点如果两个事务存在冲突操作且顺序固定就画一条有向边最终图无环则冲突可串行化。这个方法掌握后任何给的调度序列都可以按流程判断比死记硬背强太多了。封锁协议同样如此。一级封锁协议到三级封锁协议核心是什么时候加S锁/X锁、什么时候释放。我建议按表来记一级只加X锁且事务结束才释放二级在一级基础上读前加S锁但读完即可释放三级在二级基础上读锁也要事务结束才释放。再配合两段锁协议加锁阶段和解锁阶段分离要求所有加锁操作先于所有解锁操作一起记就不会乱了。故障恢复里日志文件的作用、Redo/Undo的判断是另一个高频考点。核心就一条事务已提交但数据没来得及写回磁盘需要Redo事务未提交但数据已经改了缓冲区/磁盘需要Undo。记住这个判断标准恢复类的题百分之八九十都能应对。6. 写在最后的一点心得回到最初那个问题课后习题答案本身真的重要吗我带过的学生里有把答案背得滚瓜烂熟结果考试一塌糊涂的也有习题只做了一遍但每道题都自己推导、对照教材深挖原理最后考研专业课考出高分的。区别不在答案而在答案背后的思维过程。数据库系统概论这本教材的高明之处就在于它的习题设计几乎覆盖了数据库理论的全部核心骨架。你把这本书的课后题吃透一遍再配以一定量的实际SQL操作你的数据库理论基础基本就是扎实的。这种扎实不是会考试的扎实而是到了真实业务场景里你能真正理解为什么需要索引、为什么有时要刻意冗余、为什么并发高时要引入队列和乐观锁。最后分享一个小建议学完每个章节后找一张A4白纸合上书用你自己的话说一遍这个章节到底讲了什么画一张知识结构图。你会发现能讲清楚的才是真正学会的讲不清楚的地方就是下一轮刷题的重点。这个过程没有任何捷径但它是从刷过课后题到掌握数据库系统之间最关键的一段路。