简介:本资源是《数据库系统概论(第五版)》配套的核心复习资料,专为高校计算机、软件工程等专业学生及数据库课程备考者设计,聚焦数据库系统原理核心概念的巩固与检验。内容涵盖数据管理技术演进、数据库与文件系统本质区别、数据独立性、三级模式结构(外模式/模式/内模式)、E-R模型、DBMS功能定位、数据冗余与一致性关系等20余道高频考点单选题,每题均附标准答案与简明解析,便于自测、查漏与考前速记。资源为单个PDF文件,大小1.55MB,排版清晰、题目分类明确,适合作为课堂作业补充、期中期末复习或考研基础训练材料。目前已有140人学习下载,内容紧扣教材重点,逻辑严密、表述准确,是夯实数据库理论基础的实用型练习资源。
1. 这不是一份普通题库:它是《数据库系统概论(第五版)》原理层的“思维校准器”
你手头这份《数据库系统概论第五版》数据库系统原理复习题目(选择题).pdf,表面看是几十道单选题,实则是王珊、萨师煊老师教材体系里最硬核的“概念锚点”集合。它不考你怎么写 INSERT INTO,也不问你 Navicat 怎么连 SQL Server——它专挑那些让你在面试时卡壳、在设计表结构时犹豫、在解释“为什么不能删外键引用的主键”时词穷的关键节点下手。比如第6题问“数据的物理独立性是指什么”,选项C直指本质:“用户的应用程序与存储在磁盘上数据库中的数据是相对独立的”。这背后是三级模式+两级映像的整套抽象机制,不是背定义就能蒙对的。再如第9题“产生数据不一致的根本原因是?”,正确答案是“数据冗余”,而非“没加事务”或“网络中断”——这是在逼你回到数据库设计的原点:范式、函数依赖、更新异常。它适合三类人:备考软考高项/数据库系统工程师的考生、刚学完《概论》前七章想自测理解深度的学生、以及带新人做数据库模块开发的工程师——用来快速定位团队里谁还没真正吃透“DBMS 是一组系统软件”背后的分层逻辑。这不是刷题工具,是原理层的“X 光片”。
2. 题目背后的技术骨架:从选择题反推数据库系统的核心架构
2.1 三级模式结构:每一道题都在验证你是否真懂“抽象分层”
数据库的三级模式(外模式、模式、内模式)和两级映像(外模式/模式映像、模式/内模式映像)是整个系统解耦的基石。这份题库用多道题反复锤炼这个结构:
- 第4次课第12题:“要保证数据库的数据独立性,需要修改的是( )”,答案是“三层模式之间的两种映像”。这直指核心:物理独立性靠模式/内模式映像实现(改存储结构不影响逻辑),逻辑独立性靠外模式/模式映像实现(改全局逻辑不影响应用)。
- 第2次课第4题:“描述数据库中全体数据的全局逻辑结构和特性的是( )”,答案是“模式”。注意,这里“全局逻辑结构”不是指某张表的字段,而是所有实体、联系、约束构成的完整语义视图,比如 E-R 图转化后的关系模式集合。
- 第2次课第5题:“数据库三级模式中,真正存在的是( )”,答案是“内模式”。这是常被忽略的物理真相:外模式是逻辑视图(可能多个),模式是逻辑蓝图(一个),但只有内模式对应磁盘上的实际文件组织(B+树索引、堆表、日志文件等)。
提示:当你看到“数据独立性”“映像”“模式”这些词,立刻在脑中调出三层结构图。外模式是应用看到的“窗口”,模式是 DBA 管理的“总图纸”,内模式是磁盘上真实的“钢筋水泥”。任何一道题若答错,说明这个图在你脑子里是模糊的。
2.2 数据模型与数据抽象:从现实世界到机器存储的四次跃迁
题库把数据抽象过程拆解得极为清晰,覆盖了从概念建模到物理实现的全链路:
- 第2次课第10题:“对现实世界进行第二层抽象的模型是( )”,答案是“概念数据模型”。注意这里的“第二层”:第一层是现实世界(如“学生选课”这个业务场景),第二层是概念模型(E-R 图,含实体、属性、联系),第三层是逻辑模型(关系模型,即二维表结构),第四层才是物理模型(B+树怎么存、页大小多少)。
- 第2次课第11题:“数据库在磁盘上的基本组织形式是( )”,答案是“文件”。这看似简单,却是关键认知:DBMS 不是凭空造数据,它本质是在操作系统文件(.mdf, .ibd, .db)之上构建的管理软件。SQL Server 的 MDF 文件、MySQL 的 InnoDB 表空间,都是“文件”这一层的具体实现。
- 第3次课第5题:“数据库类型是按照( )来划分的”,答案是“数据模型”。这意味着:关系型(MySQL/PostgreSQL)、文档型(MongoDB)、图数据库(Neo4j)的本质区别,不在语法或界面,而在底层如何表达“数据之间的联系”——关系模型用外键,图模型用边,文档模型用嵌套 JSON。
2.3 关系代数:SQL 语言的“编译器前端”逻辑
SQL 是声明式语言,但它的执行引擎底层跑的是关系代数。题库用大量题目强制你建立这种映射:
- 第4次课第1题:“关系代数的 5 个基本运算是( )”,答案是“并、差、选择、投影和笛卡尔积”。注意:自然连接、θ连接、除法都是由这五个基本运算导出的。例如
SELECT name FROM student WHERE age > 20对应σ_{age>20}(π_{name}(student))。 - 第5次课第2题:“下述哪个是单目运算( )”,答案是“投影”。单目运算只操作一个关系(如
π_A(R)),双目运算操作两个(如R ⨝ S)。这是判断运算复杂度的基础:笛卡尔积是双目且代价最高(O(n×m)),而选择、投影是单目且可下推优化。 - 第5次课第6题:“有两个关系 R(A,B,C) 和 S(B,C,D),则 R÷S 结果的属性个数是( )”,答案是“1”。除法运算
R÷S的结果是 R 中满足“对 S 中每个元组,R 中都有对应元组”的 A 属性值集合。其结果只含 R 中不在 S 中出现的属性(此处为 A),故属性个数为 1。这是范式分解、查询优化中识别“全称量词”的关键。
3. 从题目到实战:用 Python 快速验证关系代数运算逻辑
3.1 构建最小化测试环境:pandas 模拟关系代数
关系代数的抽象概念,用代码跑一遍就豁然开朗。我们用 pandas 模拟第5次课的题目,验证笛卡尔积、选择、投影的执行逻辑:
import pandas as pd # 模拟关系 R(A, B, C) 和 S(B, C, D) R = pd.DataFrame({ 'A': ['a1', 'a1', 'a2', 'a2'], 'B': ['b1', 'b2', 'b1', 'b2'], 'C': ['c1', 'c2', 'c1', 'c2'] }) S = pd.DataFrame({ 'B': ['b1', 'b2'], 'C': ['c1', 'c2'], 'D': ['d1', 'd2'] }) # 笛卡尔积 R × S (第4次课第1题答案 D 的核心) cartesian = R.merge(S, how='cross') # pandas 1.2.0+ 支持 print("笛卡尔积 R × S 行数:", len(cartesian)) # 输出: 8 行 (R 有 4 行, S 有 2 行, 4×2=8) # 选择运算 σ_{B='b1'}(R) (第5次课第9题 σ_f(R)) selection = R[R['B'] == 'b1'] print("选择 B='b1' 后 R 的行:", selection.to_dict('records')) # 输出: [{'A': 'a1', 'B': 'b1', 'C': 'c1'}, {'A': 'a2', 'B': 'b1', 'C': 'c1'}] # 投影 π_{A}(R) (第5次课第2题单目运算) projection = R[['A']].drop_duplicates() print("投影 A 属性去重后:", projection['A'].tolist()) # 输出: ['a1', 'a2']参数说明与逻辑:
merge(how='cross')是 pandas 对笛卡尔积的直接实现,替代了低效的手动pd.concat([R.assign(key=1), S.assign(key=1)], axis=1);R[R['B'] == 'b1']是选择运算的向量化实现,对应关系代数σ_{B='b1'}(R),时间复杂度 O(n);R[['A']].drop_duplicates()实现投影并去重,因关系模型要求属性值不可再分(第3次课第6题),故需drop_duplicates保证结果是集合而非多重集。
3.2 验证外码约束:用 SQLite 演示参照完整性
第3次课第9题问“S# 在 R 中称为( )”,答案是“外码”。我们用 SQLite 创建真实表结构,触发约束报错:
-- 创建专业表(主码 S#) CREATE TABLE department ( S# TEXT PRIMARY KEY, SN TEXT, SD TEXT ); -- 创建学生表(S# 为外码,引用 department.S#) CREATE TABLE student ( R# TEXT PRIMARY KEY, RN TEXT, S# TEXT, FOREIGN KEY (S#) REFERENCES department(S#) ); -- 插入合法数据 INSERT INTO department VALUES ('CS001', 'Computer Science', 'Building A'); INSERT INTO student VALUES ('S001', 'Zhang San', 'CS001'); -- 尝试插入非法数据:S#='MATH001' 在 department 中不存在 INSERT INTO student VALUES ('S002', 'Li Si', 'MATH001'); -- SQLite 报错:FOREIGN KEY constraint failed关键点解析:
FOREIGN KEY (S#) REFERENCES department(S#)显式声明外码,这是 DBMS 层面的强制约束;- 错误
FOREIGN KEY constraint failed直接对应第3次课第8题“主码不允许为空”的实体完整性,外码约束属于参照完整性; - 若删除
department中S#='CS001'的记录,再查student,会发现S#='CS001'的学生记录仍存在——这说明外码约束默认是NO ACTION(不级联),需显式指定ON DELETE CASCADE才能联动删除。
3.3 SQL 与关系代数映射:用 EXPLAIN 分析执行计划
第7次课第1题问“SQL 中对应‘投影’的语句是 SELECT”,但真实执行远比语法复杂。用 MySQL 的EXPLAIN查看SELECT name FROM student WHERE age > 20如何落地:
-- 假设 student 表有索引 INDEX idx_age (age) EXPLAIN SELECT name FROM student WHERE age > 20;典型输出字段解读:
type: 若为range,表示使用了 age 索引的范围扫描;若为ALL,则是全表扫描;key: 显示实际使用的索引名(如idx_age);rows: 预估扫描行数,越小越好;Extra: 若含Using index,说明是覆盖索引(只查索引不回表),对应纯投影优化;若含Using where,说明需回表过滤。
这印证了第5次课第8题“关系运算中花费时间最长的是笛卡尔积”——当EXPLAIN显示type=ALL且rows极大时,往往隐含未加连接条件的笛卡尔积风险。
4. 避坑指南:做错这5道题,说明你还没真正入门数据库原理
4.1 现象:第1次课第4题选错(“数据库避免了一切数据的重复”)
原因:混淆了“减少冗余”与“消除冗余”。数据库通过范式化降低冗余,但业务需求可能要求冗余(如订单快照保留商品名称,避免商品表更新影响历史订单)。ACID 中的 “I(隔离性)” 也允许在可重复读级别下出现幻读,本质是容忍特定场景的临时冗余。
解决:牢记教材原话:“数据库减少了数据冗余”,而非“避免一切”。冗余是权衡的结果,范式化过度会导致连接开销剧增。
4.2 现象:第2次课第13题选错(“不包括链状模型”)
原因:被字面误导。“链状模型”不是标准数据模型术语,层次模型(树形)、网状模型(图)、关系模型(表)是三大经典模型。所谓“链状”只是网状模型中的一条路径,非独立模型。
解决:死记硬背不如理解本质:层次模型是 1:N 树,网状模型是 M:N 图,关系模型是二维表。任何新名词都回归这三类判据。
4.3 现象:第3次课第7题(“码是能惟一标识元组的属性或属性集合”)漏选 C 选项
原因:误以为“码”必须是最小集合。其实“码”是泛称,包含超码(superset)、候选码(minimal superkey)、主码(selected candidate key)。第3次课第10题明确说“可以由一个或多个属性组成”,印证了码的集合性。
解决:画表验证:若(A,B)能唯一标识元组,且A或B单独不能,则(A,B)是候选码;(A,B,C)也能唯一标识,但非最小,是超码而非候选码。
4.4 现象:第4次课第5题(“参加差运算的两个关系属性个数必须相同”)选错
原因:忽略关系代数的严格定义。差运算R - S要求 R 和 S 具有相同的属性名和数据类型(同质关系),否则无法逐行比较。R(A,B)和S(C,D)不能直接相减,必须先投影重命名。
解决:用 pandas 验证:R[["A","B"]].merge(S[["A","B"]], how="left", indicator=True).query("_merge=='left_only'")模拟差运算,前提是列名一致。
4.5 现象:第6次课第6题(插入 student 表)选错 A 或 D
原因:忽视 SQL 的 NULL 规则和字符类型细节。选项 A 中男未加引号,是语法错误;选项 D 中NAME CHAR(8) NOT NULL,NULL违反非空约束;选项 C 中NO CHAR(4) NOT NULL,NULL违反非空。只有 B 满足所有约束。
解决:牢记NOT NULL字段绝不能为NULL;字符串必须用单引号;CHAR(4)存储'1031'占 4 字节,末尾补空格,但比较时自动忽略尾部空格。
5. 进阶验证:用真实数据库跑通全部题目逻辑链
5.1 构建端到端验证脚本:从题目到可执行 SQL
将题库中的核心概念转化为可运行的验证流程,覆盖从建模到查询的全链路。以下脚本在 PostgreSQL 中执行(兼容性最佳):
-- 步骤1:创建符合第2次课第11题的“文件”级存储(实际是表空间) -- (PostgreSQL 中表空间对应磁盘目录,此处用默认表空间) -- 步骤2:创建 department 和 student 表,体现第3次课第9题外码 CREATE TABLE department ( s_id VARCHAR(10) PRIMARY KEY, s_name VARCHAR(50), s_desc TEXT ); CREATE TABLE student ( r_id VARCHAR(10) PRIMARY KEY, r_name VARCHAR(50), s_id VARCHAR(10) REFERENCES department(s_id) -- 外码约束 ); -- 步骤3:插入数据,验证第3次课第2题 DBA 职责(定义内容、安全授权) INSERT INTO department VALUES ('CS001', 'Computer Science', 'AI & Systems'); INSERT INTO student VALUES ('S001', 'Zhang San', 'CS001'); -- 步骤4:执行第7次课第1题的投影查询,并用 EXPLAIN 验证 EXPLAIN (ANALYZE, BUFFERS) SELECT r_name FROM student WHERE r_id = 'S001'; -- 步骤5:模拟第5次课第4题自然连接,需共有的属性(s_id) -- 创建 course 表,与 student 共享 s_id CREATE TABLE course ( c_id VARCHAR(10) PRIMARY KEY, c_name VARCHAR(50), s_id VARCHAR(10) REFERENCES department(s_id) ); -- 自然连接:自动匹配同名字段 s_id EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM student NATURAL JOIN course; -- 步骤6:验证第4次课第1题基本运算:笛卡尔积(无 ON 条件) EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM student, course; -- 显式笛卡尔积执行逻辑说明:
EXPLAIN (ANALYZE, BUFFERS)不仅显示执行计划,还实际运行并返回耗时、缓存命中率,比单纯EXPLAIN更具说服力;NATURAL JOIN自动匹配所有同名字段(此处为s_id),若两表有多个同名字段(如s_id,created_at),则全部参与连接,这解释了第5次课第3题“等值连接属性个数 ≥ 自然连接”的原因;SELECT * FROM student, course是 ANSI-89 语法的笛卡尔积,现代 SQL 应用CROSS JOIN,但题库基于传统教材,需兼容。
5.2 关键参数对照表:题目考点与数据库配置项映射
| 题库题目位置 | 核心考点 | 对应数据库配置/命令 | 验证方法 | 注意事项 |
|---|---|---|---|---|
| 第1次课第6题(物理独立性) | 模式/内模式映像 | pg_class.relkind,pg_attribute.atttypid | 查询系统表,确认逻辑列名与物理存储类型分离 | 物理独立性体现在 ALTER TABLE ... TYPE 不影响应用查询 |
| 第2次课第14题(三层模式映射) | 外模式/模式映像 | CREATE VIEW v_student AS SELECT r_name FROM student | 创建视图后,修改 student 表增加字段,v_student 查询不受影响 | 视图是外模式的典型实现 |
| 第3次课第8题(主码非空) | 实体完整性约束 | ALTER TABLE student ALTER COLUMN r_id SET NOT NULL | 尝试INSERT INTO student(r_name) VALUES('Li Si')报错 | 主码约束自动包含NOT NULL |
| 第4次课第2题(元组唯一性) | 关系模型基本性质 | SELECT COUNT(*) FROM (SELECT DISTINCT * FROM student) t | 结果应等于SELECT COUNT(*) FROM student | 若不等,说明存在完全重复元组,违反关系定义 |
| 第5次课第7题(R ⨝ S 属性个数) | 连接运算结果 | SELECT * FROM student JOIN course USING(s_id) | 结果列数 = student 列数 + course 列数 - 1(s_id 只计1次) | USING语法显式指定共有属性,避免NATURAL JOIN的歧义 |
5.3 从题目到工程实践:一个血泪教训带来的习惯
去年我带一个团队重构电商订单库,初期按第1次课第4题的错误认知,强行追求“零冗余”,把商品名称、价格全部从 order_item 表移出,只留 product_id。上线后发现:促销活动时需实时计算满减,每次都要 JOIN 商品表,TPS 直接跌 40%。DBA 查EXPLAIN发现type=ref但rows=5000+,因为商品表太大。最终方案是:在 order_item 中冗余product_name(VARCHAR(100)),用触发器或应用层保证一致性。这让我彻底明白第9题“数据冗余是产生不一致的根本原因”——根本原因不是冗余本身,而是缺乏一致性保障机制。现在我每次设计表,必问三遍:
- 这个字段业务上是否需要历史快照?(是 → 冗余)
- JOIN 的代价是否超过冗余存储?(是 → 冗余)
- 有没有可靠的同步机制?(没有 → 宁可不用冗余)
从那以后我每次评审表结构,都强制走一遍这三问清单,哪怕多花五分钟。希望帮到你。
本文还有配套的精品资源,点击获取