简介《数据库系统概论》第五版王珊、萨师煊主编的配套习题答案面向正在学习数据库原理课程的本科生、考研复习者及自学者。答案按第1章至第16章编排覆盖绪论、关系数据库、SQL语言、数据库安全性、完整性、关系数据理论、数据库设计、数据库编程、查询优化、恢复技术、并发控制、数据库管理系统、大数据管理与数据仓库等核心内容。每道习题均给出参考答案与解析重点厘清数据、数据库、数据库系统、数据库管理系统等基础概念并结合实例说明文件系统与数据库系统的区别、使用数据库系统的优点、数据库系统的特点等高频考点帮助读者掌握答题思路。压缩包内为1个docx文档大小仅34KB内容精炼、排版清晰便于直接查看或打印。已有7539人学习下载适合对照教材逐章自测、考前集中复习和日常查阅是一份高效的数据库理论巩固资料。1. 数据库系统概论第五版习题答案别拿到手就背先学会验算王珊和萨师煊主编的《数据库系统概论》第五版几乎是国内计算机专业里流传最广的数据库教材。考研复习、期末考试甚至备考数据库系统工程师时很多人第一件事就是找课后习题答案。但这本书并没有一份能直接对应所有习题的官方答案网上流传的答案多为个人整理选择题还能直接对换到关系代数、范式分解和事务调度题错漏率很高。我见过不少同学把“选修了全部课程”的SQL答案背下来结果换一张课程表就跑错。所以这篇博客要解决的不是“去哪下载答案”而是拿到一份答案后如何自己把它验算成可靠答案。适合所有在跟第五版教材较劲的人。2. 按四大类型拆解第五版习题先把题归对类答案才不会跑偏《数据库系统概论》第五版的课后题不全是“计算题”关系代数题看运算符范式题看推导ER设计题看建模思路事务题看调度过程。可很多答案把SQL、关系代数、关系演算混在一起写读者看完也不知道自己抄的是不是本题要求。我的习惯是拿到一份答案先数一下题目里出现的关键词判断它属于下面哪一类再决定用什么工具验算。2.1 关系代数与SQL题标准答法是“关系代数定语义SQL定结果”第五版前几章的习题几乎都以学生-课程-选课三张表打底要求用关系代数或SQL表达某个查询。这类题的答案没有唯一文本因为SQL允许NOT EXISTS、NOT IN、LEFT JOIN三种写法表达同一个“不存在”但关系代数答案却只有一种运算符组合。比如“查询没有选修任何课程的学生”关系代数可以写作πSname(Student) - πSname(Student ⋈ SC)这句话必须先出现再写SQL。网上有些答案直接给SELECT Sname FROM Student WHERE Sno NOT IN (SELECT Sno FROM SC)这个写法在结果上正确但题目明确要求“用关系代数”时直接写SQL会被扣分。反过来如果题目要求写SQL你只给关系代数也不对。所以看答案的第一步是看语言和题目是否匹配。验证时我一般把关系代数手动转成SQL再用SQLite跑一遍。SQL里最容易踩的是NULLNOT IN子查询如果返回空值结果集会意外变空而NOT EXISTS不关心子查询里是否有NULL。这就是为什么很多答案在同一种题目里“有时对有时错”。第二类陷阱是去重关系代数投影默认输出集合同一学生重复满足条件只出现一次SQL的SELECT默认不去重需要自己决定是否加DISTINCT。如果网传答案里没有DISTINCT而原题关系代数又隐式去重考试时可能多出重复行这在课堂作业里通常算错。2.2 函数依赖与范式分解题答案是否等价用闭包判定范式部分的习题通常给定一个关系模式R(A,B,C,D)和函数依赖集合F让求候选键、判断属于第几范式、或分解为3NF/BCNF。这部分答案很难用肉眼对因为同一个分解目标可能有多种合法路径但“无损连接”和“保持函数依赖”这两个性质是客观的。网传答案里最常见的错误是分解结果虽然无损但把某个函数依赖丢了或者候选键算错导致后续全错。我验证这类题时先算每个属性集合的闭包。属性闭包X的含义是由X出发通过F中的函数依赖能推导出的全部属性。若X的闭包等于关系模式的全属性集合X就是超键再找最小超键才能得到候选键。拿到一份分解答案后我会做三件事第一确认分解后的每个子模式的属性并集等于R第二用表格法或算法检查是否无损分解第三检查F中每个函数依赖是否都能由分解后的子模式推断出来这一步常被人忽略。一些答案喜欢直接列出“R1(A,B,C), R2(C,D)”却不解释如何得到。这种简写只适合自己复习不适合交作业。对不上的时候不是答案一定错也可能题目里把函数依赖写成A→B和AB→C导致你有两种分解方向。要对照原题题干而不是对比“标准答案”的字符串。2.3 ER图设计题没有唯一答案但主键和联系必须可证明ER图题的主观性最强经常一个“学生借书”场景能画出很多版本。比如“出版社”可以被建模成实体也可以建模成“图书”的多值属性这种选择本身没有绝对对错但答案必须有足够强的设计理由。我核对ER图答案时看四点实体有没有确定主键多值属性有没有拉出来m:n联系有没有生成中间表弱实体有没有标注依赖关系。第五版的课后题喜欢考“系、学生、课程、教师”这类校园场景其中一个常见坑是“选修”联系带上了“成绩”属性。成绩既不是学生的属性也不是课程的属性而是联系的属性。如果答案把“成绩”放在学生实体里转换成关系模式时就会出现一个学生只能选修一门课的问题主键也会从组合键退化。还有多值属性例如“联系电话”如果建模成学生实体的一个属性转换后必须存入逗号分隔字符串这不符合第一范式。发现这类问题时基本可以直接判定答案不合格。2.4 事务与并发控制题死锁、可串行化要按“冲突图”验算并发控制章的习题常给出一个调度序列例如T1: read(A) T2: read(A) T2: write(A) T1: write(A)问这个调度是否冲突可串行化。不少答案喜欢写“是”但没有任何推导。我的做法是把每个操作按事务分组找出所有冲突对不同事务的读写或写写同一数据项且至少一方是写。然后以事务为节点、冲突方向为边画优先图有环就不是冲突可串行化。上面的例子中T2写A发生在T1读A之后、T1写A之前所以存在T2→T1T1写A和T2写A又构成另一对冲突方向需要单独画。画完图再判断。还要区分“冲突可串行化”和“可恢复调度”。如果T1读了T2写过的数据而T2最后提交那这个调度是可恢复的但它依然可能不是冲突可串行化。网传答案经常把两个概念混在一起这在期末考试里判断正误题会直接丢分。备考数据库系统工程师时优先图判断也常出现在上午题所以这道工序绕不开。以下表格汇总了我在核对不同题型答案时的参考路径方便按图索骥题型解题工具验证手段常见翻车点关系代数与SQL选择、投影、连接、除SQLite执行结果对比NULL和去重边界函数依赖与范式属性闭包、无损分解闭包脚本表格法分解不保持函数依赖ER图设计实体、联系、基数主键与多值属性检查m:n联系漏中间表事务调度冲突图、两段锁手工画优先图可恢复≠可串行化这张表不是练习题而是我检查答案时的步骤索引。3. 用SQLite把关系代数习题答案跑出来手写答案与查询结果互验有些人觉得手算关系代数就够了但SQL是成本最低的执行环境。用SQLite建三张表把“答案”转成SQL跑出来的结果就是数据库里的客观答案。只要数据造得合理就能验证手写结果是否漏条件。3.1 建库造数用最贴近课本的三张表我一般用SQLite的内存模式不用安装任何服务。下面的SQL在命令行里可以直接执行也可以保存成.db文件反复使用。-- 学生表 CREATE TABLE Student( Sno TEXT PRIMARY KEY, Sname TEXT, Ssex TEXT, Sage INTEGER, Sdept TEXT ); -- 课程表Cpno是先修课编号可空 CREATE TABLE Course( Cno TEXT PRIMARY KEY, Cname TEXT, Cpno TEXT, Ccredit INTEGER ); -- 选课表主键用复合键 CREATE TABLE SC( Sno TEXT, Cno TEXT, Grade INTEGER, PRIMARY KEY(Sno, Cno), FOREIGN KEY(Sno) REFERENCES Student(Sno), FOREIGN KEY(Cno) REFERENCES Course(Cno) ); -- 插入数据张三选了全部3门课李晨选了2门王芳选了1门赵敏没选课 INSERT INTO Student VALUES(2001,李晨,男,20,CS); INSERT INTO Student VALUES(2002,王芳,女,19,IS); INSERT INTO Student VALUES(2003,张三,男,22,CS); INSERT INTO Student VALUES(2004,赵敏,女,21,MA); INSERT INTO Course VALUES(1,数据库,NULL,4); INSERT INTO Course VALUES(2,数学,NULL,3); INSERT INTO Course VALUES(3,操作系统,2,3); INSERT INTO SC VALUES(2001,1,90); INSERT INTO SC VALUES(2001,2,85); INSERT INTO SC VALUES(2002,1,88); INSERT INTO SC VALUES(2003,1,91); INSERT INTO SC VALUES(2003,2,78); INSERT INTO SC VALUES(2003,3,69);我在造数时故意让张三选了全部三门课赵敏一门都没选这样“全部”和“空集”两类边界都有数据可查。Course表里第三门课的先修课为2是为了做题时能区分“直接先修”和“间接先修”。参数说明SC表的复合主键(Sno,Cno)保证了同一学生同一课程不会重复出现这对验证除法尤其重要外键不是必须但加上后能防止造数时写错学号。如果你在验证别的题目可以按题目要求增删数据但建议保留一个不满足条件的“干扰学生”否则查询结果只有全选或全不选无法暴露逻辑错误。在命令行执行时可以这样把SQL文件直接跑起来sqlite3 :memory: test.sql:memory:表示每次运行都新建内存数据库退出后自动销毁适合快速验证如果你想把数据保留下来复查可以改成sqlite3 textbook.db test.sql。3.2 验证“查询选修了全部课程的学生”这类关系代数答案“选修了全部课程”在关系代数里通常用除法表示在SQL里最稳妥的翻译是双重NOT EXISTS。下面这段SQL可以直接执行-- 等价于关系代数Student ⋈ SC ÷ πCno(Course) SELECT Sname FROM Student S WHERE NOT EXISTS ( SELECT 1 FROM Course C WHERE NOT EXISTS ( SELECT 1 FROM SC WHERE SC.Sno S.Sno AND SC.Cno C.Cno ) );逻辑说明外层查询遍历每个学生中间层遍历每一门课程最内层检查该学生是否选了该课程。如果存在任何一门课程使得最内层查不到记录那么中间层的NOT EXISTS为真外层的NOT EXISTS为假这个学生就不会被选中。整个过程相当于“找出那些不存在任何一门他没选的课程的学生”。跑完后应该只能查出一个人的名字张三。如果一份答案用GROUP BY和COUNT(DISTINCT Cno)实现结果也应该是张三但要注意子查询里有没有把选课表先做去重。我这里SC主键已经去重所以两种写法都稳定。再验证一道常见的“没有选修任何课程的学生”SELECT Sname FROM Student S WHERE NOT EXISTS ( SELECT 1 FROM SC WHERE SC.Sno S.Sno );返回赵敏。这个查询对应关系代数里的差运算但注意不要直接写成Sno NOT IN因为如果后面跟的子查询Sno列含有NULL结果就会变为空集。SC.Sno是外键且非空所以本表没有这个问题但当题目改成“查询没有选课程编号为1课程的学生”时子查询可能会加入其他条件让列出现NULL这时NOT IN就不可靠建议养成用NOT EXISTS的习惯。3.3 查询结果对不上时按这三个参数排查SQL跑出的结果和手写答案不一致不一定是手写答案错先查三件事第一题目里的课程集合是什么范围。如果题面说全部课程那么Course表里的每一行都要参与判断如果答案写成“选修了所有已选课程”则只要选了任意一门课的学生都会被误判成全选。第二连接字段有没有写反。Student和SC按Sno连接不是按Cno或Grade连接一旦连接条件变成S.CnoSC.Cno结果会返回完全不存在的组合数据多到没法看。第三NULL值。关系代数里的选择操作对NULL是不成立的SQL里用、、也一样不返回NULL如果答案里用了COUNT(Grade)则NULL成绩不会计入这也可能导致结果为空。桌面核对答案时我一般会把SQL结果和题目答案各写一版只要有一行差异就回溯到这三个参数上。这样下来第五版第二章到第四章的题基本都能用这种方法验完。4. 范式分解、ER图与事务调度设计类习题答案的五步验证范式分解和ER图题不是跑一条SQL就能解决的因为它们的目标不是“一个结果”而是“一组性质”。这组性质可以用算法验证所以我把这部分单独拎出来讲。4.1 用属性闭包程序验证3NF/BCNF分解的无损性属性闭包是函数依赖理论里最基础的计算。下面这个Python函数按课本里的阿姆斯特朗公理实现用于验证答案中的候选键和函数依赖是否成立# 计算属性集合在给定函数依赖下的闭包 def attr_closure(X, fds): result set(X) changed True while changed: changed False for lhs, rhs in fds: if set(lhs).issubset(result): new_rhs set(rhs) - result if new_rhs: result | new_rhs changed True return result # 示例R(A,B,C,D)FD: AB-C, C-D, D-A fds [(AB, C), (C, D), (D, A)] print(attr_closure(AB, fds)) # AB的闭包 print(attr_closure(B, fds)) # B的闭包逻辑说明函数维护一个结果集合每次扫描所有函数依赖只要某个依赖的左部已被结果集合包含就把右部合入结果集合一直循环到没有新属性产生。闭包算法在课本上会用A→B、B→C这种短链演示但实际习题里的依赖可能有6到8条手工容易漏脚本可以防止漏。参数说明X是要计算闭包的属性集合fds是函数依赖列表每个依赖用二元组(lhs, rhs)表示左右都可以是多个属性组成的字符串。执行上面示例后AB的闭包会包括A、B、C、D说明AB是超键B的闭包只有B说明B不是候选键。用这个函数还能检查BCNF分解给定分解R1上的每一个非平凡函数依赖若左部的闭包不是全属性则分解后的子模式不满足BCNF答案有问题。对于无损连接两个关系模式的分解可以直接用公共属性和依赖判断若R1∩R2是R1或R2的超键则分解是无损的。把闭包结果代进去即可。我为课程设计的标准答案是“先求候选键再逐个分解每步检查本轮分解是否无损”网上给的答案经常缺一两步用脚本补齐就能快速判错。4.2 ER图答案的5项检查清单ER图答案不好用程序检查但我有一套固定清单每拿到一个ER设计题答案就逐一对照检查项判定标准强实体主键每个强实体必须有唯一标识不能依赖其他实体多值属性电话号码、家庭成员等属性不能直接作为实体单列需单独建模1:n联系外键外键必须放在n端放反会导致数据冗余m:n联系中间表多对多必须生成独立关系模式主键通常是两端主键组合弱实体依赖弱实体必须依赖强实体且标识由部分键依赖联系决定比如题目要求设计“班级、学生、课程、教师”数据库。如果答案把“班级班级号人数学生”做成一个表将学生列表作为属性这就是带多值属性的错误建模。正确做法是学生表通过班级号外键关联班级表一个班级对应多个学生。第二常见问题是“教师授课”的m:n联系一门课程可以多个教师教一个教师可以教多门课程答案若只在课程表加教师号字段就只能表达一个教师教一门课无法处理多教师场景。做第五版课后题时还有一个判断技巧如果设计结果的关系模式里有“重复属性组”比如book1、book2、book3那一定是ER图阶段没有做多值属性处理。这种错误不需要看具体答案看到列名就足够。4.3 冲突可串行化判断答案说“可串行化”时我怎么做事务并发调度的验证核心是优先图。我以一道典型习题为例调度如下T1: read(A) T2: read(A) T2: write(A) T1: write(B) T2: write(B)先找冲突对同一数据项、不同事务、至少一个写。A上T2写A与T1读A冲突T2的写发生在T1的读之后所以有向边T1→T2。B上T1写B与T2写B冲突T1写发生在T2写之前所以有向边T1→T2。两个边方向一致优先图无环因此该调度冲突可串行化等价串行顺序是T1、T2。网传答案时常直接写“可串行化”不加解释。如果题目要求“说明理由”这种答案拿不了满分。我的做法是用表格列出冲突对再画有向边有向边一旦成环则说明答案存在反例。比如把上面调度改成T1: read(A) T2: read(A) T2: write(A) T1: write(A)在A上T2写与T1读冲突T2写发生在T1读之后边T1→T2T1写与T2写冲突T1写发生在T2写之后边T2→T1。两条边相反形成环因此不是冲突可串行化。这个例子用来验证网传答案最有效只要答案结论是“可串行化”但优先图有环就可以判定它错了。还要检查“可恢复”如果T2写A后提交T1后来才写A并提交则T1不能读到T2的未提交数据恢复性没问题但如果T1读A发生在T2写A之前则不需要等T2这里关系复杂建议回到课本定义逐条核对。5. 用“题号考点”筛选网传答案并用数据库系统工程师真题做交叉验证5.1 第五版与第六版答案错位先对题号再对答案《数据库系统概论》已经出到第六版网络检索结果里经常混着两个版本的答案。第五版和第六版的章节结构不是完全一一对应有的习题在第六版里换了序号有的章节合并。我搜索时不会直接用“第五版答案”作为唯一关键词而是把题干里的表名、条件、题号一起拼进搜索词例如“数据库系统概论 第五版 学生选课 除法 答案”。出现的结果如果是第六版题号先查章节目录确认页码和题目序号后再往下看。5.2 只看带步骤和可复现验证的答案第一看答案是否带推导过程。关系代数题至少要有运算符组合范式题至少要出现闭包或分解步骤只给最终结果的不具备任何参考价值。第二看答案是否区分关系代数与SQL。一个把“关系代数”写成“SELECT”的答案基本是外行整理或直接抄程序输出果断关掉。第三看答案里有没有提到“保持函数依赖”、“无损分解”、“避免级联回滚”这些关键词不提说明作者没理解考点更不可能保证正确。筛选后仍然需要用前面几章的方法验证一遍。我还有个习惯把验证过没问题的答案单独存成一个目录文件名用“题号-题干关键词”命名免得下次复习又搜回原来的错误页面。用数据库系统工程师真题校准时真题解析通常更严谨因为它们要经过命题组审核比个人整理的课后答案可靠。遇到课后题和软考真题考察同一知识点可以互相作为外部验证集。如果软考真题给出的SQL和执行计划和你手写答案不一致多半是你对某个语义的理解有微小偏差值得回教材再读一遍。最后留下一个可执行的做法每做完一道第五版习题把答案连同验证用SQL或闭包结果写进同一个Markdown文件下次复习直接跑一遍验证语句而不是重新翻网络答案。本文还有配套的精品资源点击获取