数据库练习卷 - 逐题知识点解析¶
考试重点
本文档严格按照《练习卷2026》参考答案,逐题分析答案为什么这么写,涉及什么知识点。
最后更新:2026-05-27 | 整理人:赫尔墨斯(小弟一号)
一、简答题(6选4,每题5分)¶
题目1:实体完整性约束判断¶
题目: 有关系模式R(A,B,C,D),已知建表语句为:
问当表中不存在任何数据的情况下,以下语句是否能正常运行,并回答原因:答案: ❌ 不能正常运行。(1分)因为主属性A的值为空值,违反实体完整性约束。(2分)
为什么这么写:
第一步:分析表结构¶
第二步:分析插入语句¶
- 只插入了 B 和 C 的值 - A 没有被赋值,所以 A = NULL第三步:检查约束¶
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| 实体完整性 | 主键中的所有属性(主属性)都不能取 NULL 值 |
| PRIMARY KEY 约束 | 定义主键,保证实体完整性 |
| 主属性 | 包含在候选码中的属性 |
| 插入操作 | 插入数据时,必须满足所有完整性约束 |
记忆口诀:
题目2:主键插入判断¶
题目:
答案: ✅ 可以正常运行(1分)。因为主属性A、B的值不为空值(2分)
为什么这么写:
第一步:分析插入语句¶
- 提供了 A='A2',B='B1'第二步:检查约束¶
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| 实体完整性 | 主键不能为空且唯一 |
| 插入操作 | 插入数据时,主键属性必须有值且不重复 |
记忆口诀:
题目3:外键删除问题¶
题目: 有关系模式如下定义:
请解释当R关系中一个元组被删除时会发生什么情况。答案: 该关系中存在外码,参照本关系的主码A,(3分)当删除一个元组时,如果该元组的A被其他元组的B所参照,会发生违反参照完整性约束的问题。(3分)
为什么这么写:
第一步:理解表结构¶
第二步:分析删除场景¶
假设数据:
- 元组1:A='A1', B=NULL
- 元组2:A='A2', B='A1'(B参照了元组1的A)
如果删除元组1:
- 元组2的 B='A1' 找不到对应的 A 值了
- 违反参照完整性约束
第三步:说明处理方式¶
可能的处理方式:
- RESTRICT/NO ACTION:拒绝删除(默认行为)
- CASCADE:级联删除(连同引用它的元组一起删除)
- SET NULL:将引用的外键设为 NULL
- SET DEFAULT:将引用的外键设为默认值
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| 参照完整性 | 外键的值必须要么等于被参照表中某个元组的主键值,要么为 NULL |
| 自引用外键 | 外键引用同一张表的主键(典型例子:员工-经理关系) |
| 删除约束 | 删除被参照元组时,需要考虑处理方式 |
记忆口诀:
题目4:并发调度问题¶
题目: 请说明下图中的并发调度存在什么问题?请给出可串行化的调度。
答案: 存在不可重复读的问题。(2分) (4分)加锁,解锁正确,错一处扣1分
为什么这么写:
第一步:识别问题¶
第二步:与脏读的区别¶
第三步:解决方案¶
第四步:可串行化调度¶
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| 不可重复读 | 同一事务内两次读取结果不同 |
| 脏读 | 读取了其他事务未提交的数据 |
| 两段锁协议(2PL) | 扩展阶段只能加锁,收缩阶段只能解锁 |
| 可串行化 | 并发执行结果等价于某种串行执行 |
记忆口诀:
题目5:BCNF判断¶
题目: 关系模式R(U,F),U=(A,B,C,D),F={(A,B)→C,(A,C)→B,B→C},请问R是否是BCNF,并说明理由。
答案: 首先求候选码,L:A LR:BC R:- N:D ADF+ =AD ABD F+ = ABCD=U ACD F+ = ABCD=U 所以候选码为:ABD,ACD。(4分) 由于给出的FD中存在决定因素不包含码的情况,所以R不是BCNF。(2分)
为什么这么写:
第一步:求候选码¶
属性分类: | 类型 | 属性 | 说明 | |------|------|------| | L(只出现在左边) | A | 只在函数依赖左边出现 | | LR(左右都出现) | B, C | 在左右两边都出现 | | R(只出现在右边) | 无 | - | | N(都不出现) | D | 在任何一边都不出现 |
计算闭包:
第二步:判断 BCNF¶
BCNF 要求: 对于每一个非平凡函数依赖 X→Y,X 必须是超码。
分析函数依赖: - (A,B)→C:X=(A,B),(A,B) 不是超码(无法推出 D) - (A,C)→B:X=(A,C),(A,C) 不是超码(无法推出 D) - B→C:X=B,B 显然不是超码
结论: 存在决定因素不包含码的情况,所以 R 不是 BCNF。
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| 候选码 | 能唯一标识元组的最小属性集 |
| 属性分类 | L类(只左)、R类(只右)、LR类(左右都出现)、N类(都不出现) |
| 闭包计算 | X⁺ = 所有能从X推出的属性集合 |
| BCNF | 每个非平凡FD的左边都必须是超码 |
记忆口诀:
题目6:数据库恢复¶
题目: 考虑如下日志记录,假设 A、B、C 的初始值均为 0:
| 序号 | 日志 |
|---|---|
| 1 | T1:开始 |
| 2 | T1:写B,B=10 |
| 3 | T2:开始 |
| 4 | T2:写A,A=8 |
| 5 | T3:开始 |
| 6 | T3:写C,C=12 |
| 7 | T1:写C,C=11 |
| 8 | T1:提交 |
| 9 | T3:写A,A=10 |
| 10 | T2:写B,B=8 |
| 11 | T2:提交 |
如果系统故障发生在 10 之后,请说明需要重做的事务,需要撤销处理的事务。并写出系统恢复后 A、B、C 的值。
答案: 重做的事务:T1;撤销的事务:T2,T3(3分) A=0,B=10,C=11(3分)
为什么这么写:
第一步:确定事务状态¶
故障发生在日志10之后:
- T1:在日志8已提交 → REDO(重做)
- T2:在日志10还在执行,日志11才提交(故障发生在10之后)→ UNDO(撤销)
- T3:从未提交 → UNDO(撤销)
第二步:恢复过程¶
A、B、C 初始值都是 0
T1 REDO(重做):
T2 UNDO(撤销):
T3 UNDO(撤销):
第三步:最终结果¶
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| RED(重做) | 已提交的事务需要重做 |
| UNDO(撤销) | 未提交的事务需要撤销 |
| 恢复原则 | 从后往前扫描日志 |
| 事务状态 | 开始、执行、提交、故障 |
记忆口诀:
二、设计与计算题¶
题目1:E-R图设计¶
题目: 设计一个某公司的项目管理系统的数据库。系统的主要功能是: - 公司下设几个部门,每个部门分别有多个员工,每个员工在当前只隶属于某一部门,每个部门有一个部门负责人 - 公司同时会有多个项目同时开展,每个项目由某个部门负责,有一个项目负责人,项目组成员可来自公司的不同部门 - 一个员工同一时间只属于某个项目 - 每个项目推进过程中各个阶段产生费用的报销单据
答案:
关系模型¶
| 关系名 | 属性 | 主码 | 外码 |
|---|---|---|---|
| 部门 | 部门编号,部门名称,部长员工号 | 部门编号 | 部长员工号→员工 |
| 员工 | 员工编号,姓名,所在部门编号,所在项目编号 | 员工编号 | 所在部门编号→部门,所在项目编号→项目 |
| 项目 | 项目编号,名称,开始时间,结束时间,预算,主要内容,部门号 | 项目编号 | 部门号→部门 |
| 单据 | 单据号,内容,所属项目编号 | 单据号 | 所属项目编号→项目 |
评分标准: 关系模式名称,属性合理每个关系模式1分,主码,外码标注正确各1分
为什么这么写:
第一步:识别实体¶
第二步:识别关系¶
从题目中提取关系:
- 部门-员工:1:N(一个部门有多个员工,一个员工属于一个部门)
- 部门-项目:1:N(一个部门负责多个项目,一个项目由一个部门负责)
- 员工-项目:N:1(一个员工同一时间只属于一个项目)
- 项目-单据:1:N(一个项目有多张单据)
第三步:确定主键¶
第四步:设置外键¶
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| E-R图设计 | 识别实体、关系、基数 |
| 基数判断 | 1:1、1:N、M:N |
| 关系模型 | 实体转换为表,关系转换为外键 |
| 主键选择 | 每个实体选择一个唯一标识符作为主键 |
| 外键设置 | 在多端设置外键指向一端的主键 |
记忆口诀:
三、综合题¶
题目1:社团管理数据库¶
题目: 设学校社团管理数据库有如下基本表: - 学生:S(sno, sname, gender, sage, sdept) - 社团:T(Tno, Tname, sno) - 社团成员:ST(sno, Tno, date)
A. 关系代数查询¶
1. 查询"计算机"系参加了社团名为"音乐社"的学生的学号、姓名
答案:
为什么这么写:
知识点: - 选择(σ):从关系中选取满足条件的元组 - 投影(π):从关系中选取指定的属性列 - 连接(⋈):按条件连接两个关系
2. 查询"计算机"系中没有参加任何社团的学生的学号
答案:
为什么这么写:
知识点: - 差运算(−):属于 R 但不属于 S 的元组
B. SQL 查询¶
1. 定义 T 表(含完整性约束)
答案:
Create table T(
Tno int,
Tname char(20),
sno char(8),
primary key(Tno),
foreign key(sno) references S(sno)
)
为什么这么写:
知识点: - 实体完整性:主键不能为空且唯一 - 参照完整性:外键必须在被参照表中存在
2. 查询参加人数超过50人的社团的名称
答案:
为什么这么写:
知识点: - GROUP BY:分组查询 - HAVING:分组后过滤 - COUNT:聚合函数,计算行数
3. 查询参加音乐社或者文学社的学生学号和姓名
答案:
SELECT DISTINCT S.sno, S.sname
FROM S, T, ST
WHERE T.Tno = ST.Tno
AND S.sno = ST.sno
AND (Tname = '音乐社' OR Tname = '文学社')
为什么这么写:
知识点: - DISTINCT:去重 - OR:逻辑或,满足任一条件即可
4. 查询"王星"同学参加的所有的社团号和社团名
答案:
为什么这么写:
知识点: - 多表连接查询 - WHERE 条件筛选
5. 查询社团负责学生是计算机系的社团号和社团名
答案:
为什么这么写:
知识点: - IN 子查询:检查值是否在子查询结果中 - 嵌套查询:一个查询嵌套在另一个查询中
6. 查询参加了学号"20010101"学生所参加的所有社团的学生学号
答案:
SELECT S.sno
FROM S
WHERE NOT EXISTS (
SELECT *
FROM ST
WHERE ST.sno = '20010101'
AND NOT EXISTS (
SELECT *
FROM ST AS ST2
WHERE S.sno = ST2.sno
AND ST.tno = ST2.tno
)
)
为什么这么写:
这是经典的"查询参加了全部课程的学生"问题的变体(所有社团)。
使用双重 NOT EXISTS 实现关系代数中的除运算(÷):
1. 外层 NOT EXISTS:对于 S 中的每个学生
2. 内层 NOT EXISTS:检查 "20010101" 参加的每个社团,该学生也都参加了
3. 如果内层 NOT EXISTS 条件成立(即不存在某个社团,20010101 参加了但该学生没参加),则该学生满足条件
知识点: - NOT EXISTS:不存在 - 双重 NOT EXISTS:实现除运算("所有"问题) - 除运算:关系代数中的除法操作
记忆口诀:
7. 新增"交响乐团"记录
答案:
为什么这么写:
知识点: - INSERT 语句:插入新记录 - 外键可为 NULL
8. 删除"影视社团"记录(考虑完整性约束)
答案:
-- 先删除社团成员表中的相关记录
DELETE FROM ST
WHERE tno = (SELECT tno FROM T WHERE Tname = '影视社团');
-- 再删除社团表中的记录
DELETE FROM T
WHERE Tname = '影视社团';
为什么这么写:
知识点: - DELETE 语句:删除记录 - 删除顺序:先删子表,再删父表 - 参照完整性约束
记忆口诀:
题目2:范式分析与分解¶
题目: 设某公司管理职工每日生产产品数量的关系模式:R(职工编号,日期,日产量,车间编号,车间主任)
说明: - 日产量为每个职工每日的产量 - 一个车间有一个车间主任 - 每个职工隶属于一个车间,一个车间有多名职工
(1)求候选码¶
答案: F = {(职工编号, 日期)→日产量,车间编号→车间主任,职工编号→车间编号} 码:(职工编号, 日期)
为什么这么写:
1. 属性分类:
- L类(只出现在左边):职工编号,日期
- LR类(左右都出现):车间编号
- R类(只出现在右边):日产量,车间主任
2. 计算闭包:
- (职工编号, 日期) → 日产量 ✓
- (职工编号, 日期) → 车间编号(通过 职工编号→车间编号)✓
- (职工编号, 日期) → 车间主任(通过 车间编号→车间主任)✓
3. 所以 (职工编号, 日期) 能推出所有属性,是候选码
知识点: - 候选码:能唯一标识元组的最小属性集 - 属性分类:L类、R类、LR类、N类 - 闭包计算:X⁺ = 所有能从X推出的属性集合
(2)判断最高范式¶
答案: R 最高为 1NF
为什么这么写:
1. 码:(职工编号, 日期)
2. 非主属性:日产量,车间编号,车间主任
3. 检查部分函数依赖:
- 职工编号 → 车间编号
- 职工编号是码的一部分,但不是整个码
- 车间编号 部分函数依赖于码
4. 由于存在非主属性对码的部分函数依赖,所以 R 只是 1NF
知识点: - 1NF:属性不可再分 - 2NF:消除非主属性对码的部分函数依赖 - 部分函数依赖:非主属性只依赖于码的一部分
记忆口诀:
(3)分解为 3NF¶
答案: 分解为3NF 职工(职工编号,车间编号) 车间(车间编号,车间主任) 日产量(职工编号,日期,日产量)
为什么这么写:
1. 分解原则:将部分函数依赖和传递函数依赖分离
2. 职工表:存储职工和车间的隶属关系
- 职工编号 → 车间编号
- 无部分函数依赖,无传递函数依赖
3. 车间表:存储车间和车间主任的对应关系
- 车间编号 → 车间主任
- 无部分函数依赖,无传递函数依赖
4. 日产量表:存储每个职工每日的产量
- (职工编号, 日期) → 日产量
- 无部分函数依赖,无传递函数依赖
知识点: - 3NF:消除非主属性对码的传递函数依赖 - 分解原则:保持无损连接和函数依赖
题目3:两段锁与死锁¶
题目: 设 T1,T2 是如下 2 个事务,其中 A、B 为数据库中 2 个数据项: - T1:如果 A>0 则更新 B=B+10 - T2:如果 B>0 则更新 A=A+5
请问使 2 事务遵守两段锁协议的情况下,是否会发生死锁。请举例说明。
答案: 有可能产生死锁。如下调度:遵循两段锁协议,并发生死锁的调度。
为什么这么写:
第一步:理解两段锁协议(2PL)¶
第二步:构造死锁调度¶
| 时间 | T1 | T2 |
|------|----|----|
| t1 | Lock(A) | |
| t2 | Read(A) | |
| t3 | | Lock(B) |
| t4 | | Read(B) |
| t5 | Lock(B) ← 等待T2 | |
| t6 | | Lock(A) ← 等待T1 |
| | **死锁!** | **死锁!** |
第三步:分析死锁原因¶
涉及的知识点:
| 知识点 | 内容 |
|---|---|
| 两段锁协议(2PL) | 扩展阶段只能加锁,收缩阶段只能解锁 |
| 死锁 | 循环等待 |
| 死锁四条件 | 互斥、持有并等待、不可剥夺、循环等待 |
| 死锁处理 | 预防、检测与恢复 |
记忆口诀:
四、核心口诀汇总¶
完整性约束¶
范式判断¶
SQL查询¶
事务并发¶
数据库恢复¶
题目知识点解析完成!祝考试顺利!🎓