☰
数据库系统概论复习资料:从散点知识到系统自检的实战指南
2026/10/9 7:48:57 网站建设 项目流程

简介:《数据库系统概论》各章复习试题及答案(完整版)是一份面向高校学生、数据库初学者及备考人员的自测复习资料。内容系统梳理数据库的基本概念、数据管理技术发展、三级模式与两级映射、数据模型、完整性、安全性、并发控制与恢复等核心知识点,并按章节配以选择题、填空题、简答题及参考答案,适合用于检验学习效果、考前强化和查漏补缺。覆盖从人工管理到分布式与云数据库的演进,并结合常见考点与易错点,帮助读者由浅入深理解数据库原理。压缩包内仅含1个PDF文件,大小1.08MB,排版完整,方便在电脑、平板或手机端直接阅读和打印。目前已有360人学习/下载,若正在备考数据库课程考试,这份资料能提供清晰的知识框架与大量典型题目,帮助快速定位薄弱环节并巩固重点。

1. 数据库系统概论复习资料:它不是用来背的,而是用来检验的

很多学习者手里都有一份标注“完整版”的数据库系统概论各章复习试题及答案,最常见的用法却基本是同一个:从头做到尾,对完答案,合上PDF,一周后全忘光。数据库系统概论这门课挂科率常年高,问题往往不在题量不够,而是知识太散——数据模型、关系代数、范式理论、SQL、事务并发、故障恢复,每一章都独立讲,考试却要把它们串起来考。这份试题真正的作用,是把散在各章的知识点变成一张可以自检的网:概念题查记忆漏洞,SQL题查动手能力,范式题查推导逻辑,事务题查理解深度。适合三类人:期末备考的在校生、复试前需要补理论基础的考生、以及工作后发现自己连表结构都设计不好的转行者。接下来说的,是这套资料更高效的打开方式。

2. 先把地图摊开:数据库系统概论的章节体系与考点分布

2.1 贯穿全书的逻辑主线:从现实世界到关系模式

数据库系统概论这门课,表面上分了很多章,实际只讲了一件事:现实世界的数据,如何一步步变成计算机里可查询、可更新、不出错的关系模式。整本书的章节排布,就是在回答这条链路上的每一环。

最前面是绪论和数据模型,回答“数据怎么描述现实世界”;接着是关系数据库和关系代数,回答“关系这种模型为什么能成为主流”;然后是SQL,回答“怎么用标准语言操作关系”;再往后是安全性和完整性,回答“怎么防止用户干坏事”;范式理论回答“表设计成这样会不会出问题”;数据库设计回答“从需求到表结构的完整流程”;事务、并发控制和恢复回答“多用户同时访问时怎么保证不出错”;最后的数据库新技术,则是把前面的关系模型放到大数据背景下重新审视。

理解了这条主线,再去看试题集就会很清晰:所谓“各章复习试题”,本质上是这条主线上的每一个环节各出几道题,检验你是否真正打通了链路。如果只看单章孤立地背,就会出现一种典型现象——每一章的选择题都能对一半以上,但综合设计题完全无从下手。因为综合题考的不是某一章,而是“ER图导出关系模式 → 判断范式 → 写SQL → 分析并发问题”一整条流水线。

2.2 各章考点权重与复习优先级

不同章节在考试中的分值占比差异很大,直接用试题反推就能看得很清楚。综合多套试题和常见教材的分布,大致可以整理成下面这张表。

章节板块常考题型典型考点分值权重复习优先级
绪论与数据模型选择、简答三级模式两级映像、数据模型分类低理解即可
关系代数与关系运算大题选择、投影、连接、除运算中必须会写
SQL语言大题建表、嵌套查询、分组统计、视图高最核心得分项
安全性、完整性选择、简答GRANT/REVOKE、触发器、约束类型中低背关键词
范式与函数依赖大题闭包、候选键、范式判定、分解高拉分关键
数据库设计大题ER图、ER图转关系模式高必考且易得分
事务与并发选择、大题ACID、冲突可串行化、两段锁、隔离级别高理解型难点
故障恢复选择、简答日志、REDO/UNDO、检查点中流程要背熟
数据库新技术选择NoSQL、分布式、云计算概念低考前浏览即可

这个权重分布基本反映了复习的现实策略:SQL、范式、数据库设计、事务并发这四块,占了试卷的大半壁江山,也是这道PDF里题目密度最高的地方。复习的时候如果时间有限,把这四块啃透,比面面俱到地背绪论要划算得多。

值得注意的是,很多学习者会低估关系代数的重要性,觉得现在写SQL没人用关系代数。但试题里关系代数大题的价值不在于“实际工作用不用”,而在于它是理解SQL查询优化器和连接顺序的唯一理论工具。考试直接考,面试偶尔也会问,不能跳过。

2.3 用试题反推章节重点:两种读题方法

拿到这份资料,不要急着从头开始做。先花二十分钟把目录和题型分布过一遍,明确自己处在哪个阶段,再选择对应的使用方式。

第一种方式是“按章节刷”:适合第一轮复习,配合教材逐章推进。看一章教材,做一章试题,目的不是得分,而是暴露漏点。这一轮允许翻书、允许看答案,但每道错题旁边必须写清楚错误原因:是概念没记住,还是推导步骤出了错,还是压根没看懂题目在问什么。这样一轮下来,你会得到一份非常诚实的“漏洞清单”。

第二种方式是“按题型刷”:适合第二轮。把所有选择放一起刷一遍,把所有SQL大题放一起连做五道,把所有范式题放一起连推五道。这个方法的逻辑是,同一题型的出题套路非常固定,连续做会让你快速识别题目背后的固定结构。比如范式判定题,问法翻来覆去就是“求候选键”“判第几范式”“分解成3NF”,套路感一旦建立,做题速度和正确率会同时上去。

3. 把试题做“厚”:典型题型的标准解法与踩分点

3.1 ER图转关系模式的三步法与四个边界点

ER图转关系模式是数据库设计章节的大题主力,也是整份试题里性价比最高的分。因为它套路极其固定,掌握了规则就能稳定得分。

常见做法是分三步走:第一步,把每个实体各自转成一张表,实体的属性就是表的列;第二步,把实体间的联系按类型分别处理;第三步,检查合并,把能合并的表尽量合并,减少连接开销。核心规则是:1:1联系可以并入任意一端;1:N联系并入N端;M:N联系必须单独建表,主键是两端主键的组合。

-- 学生(学号, 姓名, 班级) -- 课程(课程号, 课程名, 学分) -- 学生选课,M:N联系,选课有属性“成绩” -- 第一步:实体转表 CREATE TABLE Student ( Sno CHAR(9) PRIMARY KEY, Sname VARCHAR(20) NOT NULL, Sclass VARCHAR(20) ); -- 第二步:M:N联系单独建表 CREATE TABLE SC ( Sno CHAR(9), Cno CHAR(4), Grade SMALLINT, PRIMARY KEY (Sno, Cno), -- 组合主键,体现M:N联系 FOREIGN KEY (Sno) REFERENCES Student(Sno), FOREIGN KEY (Cno) REFERENCES Course(Cno) );

逻辑说明:这段建表语句演示的是最典型的M:N联系处理方式。SC表的主键由Sno + Cno组合而成,这意味着同一学生对同一课程只能有一条选课记录,从表结构层面保证了数据的唯一性。两个外键分别指向两张实体表,保证引用完整性。Grade作为联系自身的属性,只能落在联系表里,不能塞进学生表或课程表,否则会出现大量空值和冗余。参数说明:PRIMARY KEY (Sno, Cno)是复合主键的写法;FOREIGN KEY ... REFERENCES用于声明外键。实际问题中如果设计者把成绩放进了学生表,会导致学生表里每个学生有多条记录,主键被迫写成复合形式,反而破坏了实体表的语义。

四个边界点是需要额外注意的地方:一是1:1联系的合并方向选择,通常并入参与度较小或访问频繁较低的一端;二是三元联系的处理,一般单独建表,主键是三端主键的组合;三是自联系的处理,比如“职工”表里的“经理”字段,实际是职工表对自身的1:N联系,要用外键指向自身主键;四是弱实体的处理,弱实体的主键要包含其依赖的强实体的主键。试题答案里经常出现“联系并入实体”的合并写法,如果合并后不产生冗余,这样的答案通常也是可接受的。

3.2 函数依赖与范式判定:一套可以机械执行的判断流程

范式判定题一直被当成“玄学”,很多人觉得每次做的结果都不一样。实际上它的判定流程可以写成一套非常机械的步骤,只要每一步都按规则执行,结果必然唯一。

固定的流程是:第一步,根据函数依赖集求属性闭包,找出所有候选键;第二步,检查非主属性对候选键的依赖方式,判断是否满足2NF;第三步,检查是否有传递依赖,判断是否满足3NF。每上升一个级别,就多一道检查。如果候选键求错了,后面的判定全部白做,所以闭包求解是整道题的地基。

# 求属性闭包 X+ 的固定算法 def closure(attrs, fds): result = set(attrs) changed = True while changed: changed = False for lhs, rhs in fds: # 遍历每条函数依赖 X -> Y if set(lhs).issubset(result) and not set(rhs).issubset(result): result |= set(rhs) changed = True return result # 示例:R(学号, 课程号, 姓名, 院系, 院系主任) # 函数依赖:学号->姓名, 学号->院系, 院系->院系主任, (学号,课程号)->成绩 # 求候选键时,先找出所有不出现在任何函数依赖右侧的属性

逻辑说明:这段代码实现的是属性闭包求解,核心逻辑是不断把能推导出的属性并入结果集,直到结果集不再变化。lhs和rhs分别代表函数依赖的左部和右部。理解这段代码的关键在于:闭包计算的本质是“传递闭包”,即反复应用已有函数依赖,看还能推出什么新属性。参数说明:fds是函数依赖列表,每一项是一个二元组。实际做题时不需要写代码,但可以手动模拟这个循环过程:先写出已知闭包,看哪条依赖的左部已包含在闭包中,就把它右部的属性加进来,重复直到稳定。求候选键的方法则是先看“只出现在左部从未出现在右部”的属性集合,如果它的闭包已经覆盖全属性集,那它就是唯一候选键;如果不是,需要逐一尝试补充属性。

范式判定最常翻车的点在于:把“主属性”和“非主属性”搞混。主属性是候选键里的任一属性,非主属性是候选键之外的属性。判断2NF看的是非主属性是否部分依赖候选键,判断3NF看的是非主属性是否传递依赖候选键。只要候选键求对,这两步检查就是纯粹的查表操作,没有任何玄学成分。

3.3 SQL大题:连接条件写不对,一半分数就没了

SQL大题是整份试题里最稳定的得分项,但失分点也很稳定——连接条件。很多学习者写多表查询时,WHERE子句里只写了选择条件,忘了写连接条件,导致结果变成笛卡尔积;或者连接条件写反了,把A.Sno = B.Sno写成A.Sno = B.Cno,结果查询出来的数据全是错的。

-- 典型试题:查询选了“数据库”课程且成绩大于85分的学生姓名和成绩 SELECT S.Sname, SC.Grade FROM Student S JOIN SC ON S.Sno = SC.Sno -- 连接条件 JOIN Course C ON SC.Cno = C.Cno -- 连接条件 WHERE C.Cname = '数据库' -- 选择条件 AND SC.Grade > 85;

逻辑说明:这段SQL把连接条件写在ON子句、选择条件写在WHERE子句,职责分离非常清晰。JOIN ... ON先把两张表按关联字段拼接成一张大表,再用WHERE在大表中做筛选。参数说明:连接条件的字段要来自两端的表,且类型一致;选择条件里用到的表别名要在前面定义过。实际丢分场景往往是漏写第二个JOIN——因为“学生—选课—课程”是三张表关联,少连一张表结果就会直接少一列或出现重复行。另一个常见写法是把JOIN省略,全部写在WHERE里,效果等价但可读性差,阅卷时容易因为漏写一个条件被扣分。

还有一个高频考点是分组统计。这类题目的固定结构是“按什么分组,就按什么查询”,但分组之后WHERE不能再筛选聚合结果,必须改用HAVING。试题里常用的一处陷阱是:用WHERE对聚合结果做筛选,这在SQL语法上直接报错,运行时翻车,是考场上相当典型的低级失分点。

3.4 并发调度可串行化判断:别靠猜,靠冲突对

事务并发章节的题目在试卷里存在感很强,而且往往是拉分题,因为很多学习者靠直觉判断“这两个调度看起来一样”,但拿不出依据。判断冲突可串行化的标准方法很机械:找出所有冲突对,画优先图,看有没有环。有环就不可串行化,没环就存在一个等价串行顺序。

冲突对的定义是:两个来自不同事务的操作,操作同一个数据项,且其中至少有一个是写操作。读读不冲突,读写、写读、写写都冲突。判定时,如果某调度里T1的写操作在T2的读操作之前,就在优先图里画一条T1 -> T2的边。最后检查有没有环。

调度片段冲突分析优先图判断
T1: R(A), T2: R(A)读读不冲突无边,无环
T1: R(A), T2: W(A)读写冲突,T1先于T2T1 -> T2,无环
T1: W(A), T2: W(A), T1: W(B), T2: W(B)写写冲突两次T1->T2 且 T2->T1,有环

这张表展示了最基础的冲突判断逻辑。前两行都无环,存在可串行化调度;第三行出现了双向边,优先图成环,调度不可串行化。实际做题时,只需要画出优先图,检查有没有环,这道题就基本拿满了。真正的失分点在“漏找冲突对”——只盯着同行操作看,忽略了不同数据项之间的交叉顺序,导致优先图画不完整,环判断自然出错。

4. 两块硬骨头:闭包求解与并发控制,值得单独啃

4.1 候选键求解:从闭包出发,别靠肉眼观察

候选键求解是范式判定、分解、BCNF判定的公共前提,也是整份试题里错误率最高的环节。很多学习者的习惯是“肉眼看函数依赖,猜一个属性组合当候选键”,然后直接往下做,这种做法在闭包计算上栽跟头是迟早的事——因为你无法证明自己猜的组合已经覆盖了全部属性。

固定做法是:先找出所有不出现在任何函数依赖右部的属性,记作集合X;然后求X+,如果X+等于全集U,那么X就是唯一的候选键;如果不是,就依次尝试往X里加入一个属性,重新求闭包,直到闭包覆盖全集。注意,候选键不唯一时,需要把所有组合都列出来。

def find_candidate_keys(attrs, fds): U = set(attrs) # 左部出现的属性集合 left_attrs = set() for lhs, rhs in fds: left_attrs |= set(lhs) # 从不在任何右侧出现的属性,候选键必须包含它们 essential = U - set().union(*[set(rhs) for _, rhs in fds]) candidates = [] # 从 essential 开始,逐步扩展属性组合,求闭包验证 # 如果 essential 的闭包不是全集,需要尝试补充其他属性 return candidates

逻辑说明:这个框架的核心逻辑是“候选键必须包含不出现在任何函数依赖右侧的属性”,因为这些属性无法由其他属性推导得出。essential集合是所有候选键的交集部分。参数说明:attrs是全属性集合,fds是函数依赖列表。实际手算时不需要遍历全部组合,只需要从essential出发,逐个尝试加入左侧出现过但右侧没有的属性,每次求一次闭包,直到找到能覆盖U的最小组合。一个小技巧:如果某个属性的闭包覆盖了全集,任何包含它的超集都不再是候选键,可以剪枝。

这块内容值得单独花时间啃,是因为几乎所有高阶题都建立在它的基础上。关系模式分解、判断是否保持函数依赖、判定是否无损连接,全都要用到闭包。把它练熟,等于给整章题目打通了任督二脉。

4.2 两段锁协议与隔离级别:并发控制的两种叙述语言

两段锁协议和隔离级别,是同一个事物的两套叙述语言,很多学习者把它们混在一起背,结果考试一换问法就翻车。两段锁是“实现层”的协议:事务分两阶段,第一阶段只能加锁不能解锁,第二阶段只能解锁不能加锁。隔离级别是“标准层”的定义:读未提交、读已提交、可重复读、串行化,对应不同的异常容忍程度。

两套语言对应关系大概是:可串行化调度对应加锁直到事务结束;可重复读对应读锁保持到事务结束,写锁同样保持;读已提交对应读锁在读操作后立即释放,写锁保持到事务结束;读未提交则连写锁都在提交前提前释放。考试常考的是“给定一个调度,说出它属于哪个隔离级别”,或者反过来“在可重复读级别下,这个调度会不会出现幻读”。

做题的固定思路是:先看事务是否满足两段锁,再对照隔离级别的定义判断允许哪些异常。试题里的经典陷阱是“严格两段锁”和“两段锁”的区别——严格两段锁要求事务持有的所有锁在提交后才释放,而普通两段锁只要求在释放第一个锁之后不能再加锁。如果试题问的是“是否满足两段锁协议”,回答时不要自动按严格两段锁的条件去套,否则会把正确答案判错。

4.3 故障恢复的判断顺序:为什么总是先分析日志再决定动作

故障恢复章节的题目在试题集里篇幅不大,但每次都有那么一两道,而且错误率常年稳定在高位。原因在于很多学习者在背“REDO/UNDO”的规则时,只记住了“有日志就REDO,没日志就UNDO”,却忽略了判断顺序的问题。

标准流程是:先从后往前扫描日志,找到最后一个检查点;再从最后一个检查点开始往前找,找到最早的活动事务;然后根据日志记录的内容,判断每个事务是否在故障发生时已提交。已提交但数据没落盘的事务需要REDO,未提交的事务需要UNDO。这个顺序不能反——如果先决定REDO还是UNDO,再去查日志,就会把已提交事务和未提交事务搞混。

# 故障恢复判断的手工模拟路径 # 1. 从日志文件末尾向前扫描,找到最近一次 <checkpoint> 记录 # 2. 记录检查点时所有活动事务的列表 # 3. 从检查点继续向前扫描,把新遇到的事务加入活动列表 # 4. 对每个活动事务,检查其是否包含 <commit> 记录 # - 有 commit:该事务在故障前已提交,需要 REDO # - 无 commit:未提交,需要 UNDO

逻辑说明:这条命令序列模拟的是手工恢复分析的流程。关键在第4步——不是看“有没有更新日志”来决定REDO,而是看“有没有提交记录”。已提交的事务即使日志已经写入,其数据页也可能还在内存缓冲池里没来得及落盘,所以必须重做;未提交的事务虽然修改过数据页,但结果不可见,必须回滚。参数说明:checkpoint记录中的活动事务列表是分析起点,它决定了哪些事务需要回溯检查。如果跳过检查点直接从末尾扫到开头,效率低且容易遗漏早期事务,实际做题时经常因为少算一个事务而丢分。

5. 复习备考避坑指南:五个高频翻车场景的根因与对策

5.1 现象:选择题全对,综合大题写不出来

很多学习者刷完这份PDF后会发现一个尴尬事实:选择题和判断题正确率不错,但遇到“画出ER图并转换成关系模式”“给出函数依赖集求候选键并分解”这类大题,直接卡住。这不是知识点没记住,而是记忆型学习和操作型学习的区别——选择题只要“认得对”就能做对,大题需要“写得出来”。

原因在于:选择题的选项本身就是提示,看到正确答案时会有似曾相识感,这种感觉被误认为是“掌握了”。但合上书后,从零开始画ER图、写SQL,大脑里没有任何提示可用,顿时一片空白。

解决办法是:第一轮刷题时强制自己以“输出”代替“选择”。遇到选择题,盖住选项,先自己口头说出答案和理由,再说出另外三个选项为什么错。遇到大题,直接在纸上从第一步写到最后一步,中间不许翻书。这个过程会很痛苦,但它能把“认得”转化为“写得出来”,是复习中价值最高的练习方式。

5.2 现象:范式判定题每次做出来的结果都不一样

同一个函数依赖集,每次判定出来的范式级别可能不同,甚至同一个人隔一天再做,结果也变了。这会让人怀疑范式判定是不是玄学,实际上几乎都是同一个步骤出了问题:候选键求错了。

原因通常有两个。一是候选键只求了一半,只找到一个键就停下,没有检查是否还有其他候选键。二是闭包计算过程中漏掉了某个函数依赖,比如传递依赖中需要通过中间属性才能推出的那些属性,少推一步,闭包就不完整,后续全部判错。

解决办法是建立一个自检习惯:每次求闭包时,把函数依赖集按左部排序,逐个检查,每加入一个新属性就划掉该条依赖,保证每条依赖都被用过至少一次。求完候选键后,花10秒验证一下候选键的闭包是否等于全部属性集,不等于则一定漏推了。这个习惯能把范式题的通过率提高一大截。

5.3 现象:SQL代码能看懂,自己写就卡住

看答案时觉得SQL非常简单,自己动手写却不知道从哪张表开始。这是SQL学习中最普遍也最挫败的现象,本质是缺少“查询骨架”意识。

原因在于:读SQL是从结果倒推过程,看到SELECT就知道要查什么,看到FROM就知道从哪查,逻辑自然顺畅。但写SQL是正向构建,需要自己决定先连哪张表、再连哪张表、最后筛什么条件。很多学习者的卡点集中在“不知道以哪张表为起点”,而不是真的不懂语法。

解决办法是固定一套书写顺序:先读题目,圈出涉及的所有表名;再确定表与表之间的连接字段,写出每个JOIN;然后写筛选条件到WHERE;最后才考虑是否需要分组和排序。这套顺序的顺序是固定的,每一步的产出都是下一步的输入,可以有效降低从零构建的认知负担。刷题时所有SQL题都按这个顺序在草稿纸上先写“表连接图”,再写代码,几轮之后起手卡顿的问题会明显减少。

5.4 现象:事务隔离级别和加锁协议混为一谈

试题中经常出现这种问法:“在可重复读隔离级别下,下面这个调度是否会出现丢失更新?”很多学习者看到“可重复读”就开始背定义,完全忘掉了可重复读是通过什么机制实现的,导致回答时逻辑混乱。

原因在于把标准层的概念和实现层的概念当成两套独立知识在背,没有建立映射关系。隔离级别是结果定义,锁协议是实现手段,同一个级别可以有不同的加锁实现,但考试通常只考最常见的映射关系。

解决办法是画一张对应关系表,把常用的四种隔离级别和它们允许的异常、典型的锁协议实现放在一起对照记忆,做题时先判断调度里出现了哪类冲突,再反推它被哪个隔离级别允许。这张表不需要背得很死,但要能在做题时快速提取。

5.5 现象:只背结论不推过程,换个数据就不会做了

同一道范式题,把函数依赖里的属性名从“学号、课程号”换成“订单号、商品号”,很多学习者就做不出来了。这在复习末期尤其常见,因为这时大家更倾向于背“标准答案”而不是重新推导。

原因在于:题目做了很多,但没有意识到自己记住的是“这道题的答案”,而不是“这类题的解法”。考试只要换一种属性命名、换一个关系模式,原来背的答案就完全失效。

解决办法是刻意做“变式练习”:每道做错的题,把属性名和具体值替换掉,自己重新完整做一遍;再尝试改变函数依赖的个数,增加一条或删一条,观察范式级别是否改变。这样练习的本质是在训练“解法”而非“答案”,到考场上遇到任何数据都能稳住。

6. 一套让资料越用越薄的复盘方法

复习到后期,一个很现实的问题是:题刷完了,错题也看过了,但关上PDF,总觉得心里没底。这里分享一套我一直在用的复盘方法,核心思路是让资料越用越薄,最后只需几张A4纸就能复述整门课。

具体操作分三轮。第一轮,每做完一章的题,用三句话概括这一章解决什么问题、用什么手段解决、常考哪类题型;写在一张A4纸的顶部。第二轮,把错题对应的知识点浓缩成关键词,写在同一张纸的中部,每个知识点后面只写一个典型的坑。第三轮,考前不看PDF只翻这几张纸,对着每章的关键词,尝试用自己的话把知识点完整讲出来,卡住的地方再回去翻原资料。三轮之后,几百页的复习资料会被压缩成几张纸,心理压力也小很多。

我自己的教训是:早期复习只顾刷题,觉得题做得多就稳了,结果考试时遇到一道原题换了数据,直接卡住,出考场翻书才发现是同一类型。从那以后我强制自己做变式练习和讲述练习,效果远好于重复刷题。这套方法不一定适合所有人,但它逼着你从“我记得这个答案”走向“我能推导出这个答案”。希望这套复盘方法能帮你把手里的资料真正用出效果,也希望你在考场上不再被换了个数据就认不出来的题难住。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询