简介:这份资源是钱学忠《数据库原理及技术》教材的配套习题答案,面向高校计算机专业学生、备考数据库相关课程考试的学习者,以及希望巩固数据库理论与实践基础的自学者。内容围绕数据库设计、SQL语言、关系数据库理论、数据库管理系统与数据库管理等核心章节展开,可帮助读者在完成课后练习后对照答案查漏补缺,理清E-R模型转换、关系代数演算、范式规范化等易错知识点。资源以rar压缩包形式提供,整体约16.69MB,文件总数与具体类型明细上游暂未提供,下载后可按章节顺序逐题核对。目前已有693人学习下载,适合作为课程复习与习题自测的辅助材料,配合教材使用能更高效地掌握数据库设计与管理的关键方法。
1. 数据库原理及技术(钱学忠)答案:一份被低估的课后题拆解手册
如果你正在上《数据库原理及技术》这门课,用的恰好是钱学忠老师编的那本教材,那你大概率经历过这个场景:课后习题翻来覆去看了三遍,关系代数那道题还是不知道从哪下手,SQL 写出来跑不通,范式分解更是像在做玄学推理。这份“答案”资源,本质上就是针对该教材课后习题的一套完整参考解答,覆盖关系模型、SQL 语句、范式理论、事务与并发控制等核心章节。它适合正在跟课、准备期末、或者考研复习数据库的读者,用来对照自己的解题思路,而不是拿来直接抄。我拿到这份资料后逐章翻了一遍,下面把它的结构、用法和几个容易翻车的地方拆开讲。
2. 这份答案到底覆盖了什么:章节映射与题型拆解
2.1 教材章节与答案的对应关系
钱学忠这本《数据库原理及技术》的章节编排,基本遵循经典数据库教材的脉络:从绪论和数据模型起步,经过关系代数、SQL、规范化理论,再到事务管理、并发控制和恢复技术。这份答案资源按章节组织,每一章对应教材课后习题的编号给出参考解答。
我拿到手后第一件事是对目录。常见做法是先把教材的章节目录抄下来,然后逐条比对答案文件的章节标题,确认没有缺章或错位。实际比对下来,覆盖情况大致如下:
| 教材章节 | 答案覆盖情况 | 题型分布 |
|---|---|---|
| 绪论与数据模型 | 完整 | 概念简答、模型对比 |
| 关系代数与关系演算 | 完整 | 代数表达式、元组/域演算转换 |
| SQL 基础 | 完整 | 建表、查询、视图、权限 |
| 规范化理论 | 完整 | 函数依赖、范式判定、分解 |
| 事务与并发控制 | 完整 | 调度分析、锁协议、隔离级别 |
| 数据库恢复技术 | 完整 | 日志分析、检查点、redo/undo |
从题型分布看,关系代数和范式分解这两块占的比重最大,也恰恰是最容易出错的部分。SQL 部分的答案相对直观,但有些题涉及嵌套查询和聚集函数的组合,光看答案不一定能理解为什么这样写。
2.2 不同题型的拆解思路
概念简答题的答案,我一般不会死记,而是先看它用了哪些关键词。比如问“数据库三级模式结构是什么”,答案里一定会出现外模式、概念模式、内模式这三个词,以及两层映像。抓住这几个锚点,用自己的话组织就行。
关系代数题是重灾区。答案里给出的表达式往往很简洁,但省略了推导过程。我的习惯是拿到答案后反向推:先看结果是什么关系,再看用了哪些运算(选择、投影、连接、除),最后验证每一步的输入输出是否对得上。除法运算尤其要小心,很多答案直接给结果,但中间步骤需要自己补。
SQL 题的答案通常可以直接在数据库里跑。我一般会建一个测试库,把教材里的示例表结构建好,然后把答案里的 SQL 逐条执行,看结果是否和题目要求一致。这一步能过滤掉不少印刷错误或笔误。
范式分解题,答案给的分解结果不一定唯一。这时候不能只看“对不对”,还要看“好不好”——是否保持函数依赖、是否无损连接。答案里如果只给了一个分解方案,最好自己再想想有没有其他等价方案。
3. 怎么用这份答案复现解题过程:从建库到验证
3.1 搭建本地测试环境
要验证 SQL 和关系代数相关的答案,最直接的办法是在本地建一个数据库。MySQL 和 PostgreSQL 都行,我一般用 MySQL,因为教材里的示例大多兼容。
安装好之后,先建一个练习库:
-- 创建练习数据库 CREATE DATABASE db_practice DEFAULT CHARACTER SET utf8mb4; -- 切换到该数据库 USE db_practice; -- 创建教材中常见的学生-课程-选课三表结构 CREATE TABLE Student ( Sno CHAR(8) PRIMARY KEY, -- 学号 Sname VARCHAR(20) NOT NULL, -- 姓名 Sage INT, -- 年龄 Sdept VARCHAR(20) -- 所在系 ); CREATE TABLE Course ( Cno CHAR(4) PRIMARY KEY, -- 课程号 Cname VARCHAR(40) NOT NULL, -- 课程名 Ccredit INT -- 学分 ); CREATE TABLE SC ( Sno CHAR(8), -- 学号 Cno CHAR(4), -- 课程号 Grade INT, -- 成绩 PRIMARY KEY (Sno, Cno), FOREIGN KEY (Sno) REFERENCES Student(Sno), FOREIGN KEY (Cno) REFERENCES Course(Cno) );这段建表语句对应的是教材里最经典的三表模型。Student存学生基本信息,Course存课程信息,SC是选课关系,主键是学号和课程号的组合。外键约束保证引用完整性。字符集用utf8mb4是为了避免中文乱码,这个坑后面还会提到。
建完表后插入几条测试数据:
INSERT INTO Student VALUES ('20210001', '张三', 20, '计算机系'), ('20210002', '李四', 21, '数学系'), ('20210003', '王五', 19, '计算机系'); INSERT INTO Course VALUES ('C001', '数据库原理', 4), ('C002', '数据结构', 3), ('C003', '操作系统', 4); INSERT INTO SC VALUES ('20210001', 'C001', 85), ('20210001', 'C002', 90), ('20210002', 'C001', 78), ('20210003', 'C003', 92);有了这些数据,就可以把答案里的 SQL 逐条跑一遍,对照结果。
3.2 关系代数答案的验证方法
关系代数没法直接在数据库里跑,但可以翻译成 SQL 来验证。比如答案里给出一个除法运算的结果,你可以把它转成NOT EXISTS的双重否定形式来验证。
举个例子,题目要求“查询选修了全部课程的学生学号”,关系代数里用除法表示为π_Sno,Cno(SC) ÷ π_Cno(Course)。翻译成 SQL 就是:
-- 查询选修了全部课程的学生 SELECT DISTINCT Sno FROM SC AS X WHERE NOT EXISTS ( SELECT * FROM Course AS C WHERE NOT EXISTS ( SELECT * FROM SC AS Y WHERE Y.Sno = X.Sno AND Y.Cno = C.Cno ) );逻辑是:对于每个学生,如果不存在一门课程是他没选的,那他就选了全部课程。双重NOT EXISTS是除法运算的标准 SQL 翻译模式。跑一下结果,如果和答案一致,说明你的理解没问题。
参数说明:X是外层的学生选课记录,C是课程表,Y是内层用来匹配当前学生和当前课程的选课记录。三层嵌套的顺序不能乱,乱了语义就变了。
3.3 范式分解题的验证步骤
范式分解的答案验证起来最麻烦,因为分解结果不唯一。我的做法是分三步走:
第一步,检查分解后的每个关系模式是否满足目标范式。比如答案说分解到 3NF,那就逐个检查每个模式里有没有非主属性对码的传递依赖。
第二步,验证无损连接。用 Chase 算法或者直接检查分解是否包含原关系的候选码。如果分解后的某个模式包含了原关系的候选码,那一定是无损的。
第三步,验证是否保持函数依赖。把原关系的函数依赖集投影到每个分解后的模式上,取并集,看是否和原依赖集等价。
这三步走完,基本能判断答案给的分解方案是否合理。如果答案只给了一个方案,你可以自己再试一个不同的分解,对比两个方案的优劣。
4. 避坑与排查:那些年我对照答案时翻过的车
4.1 现象:SQL 答案跑不通,报语法错误
原因:教材里的 SQL 可能基于标准 SQL 或者某个特定数据库的方言,直接拿到 MySQL 里跑不一定兼容。比如教材里可能用了FULL OUTER JOIN,但 MySQL 不支持这个语法。
解决:先确认答案里的 SQL 是针对哪个数据库写的。如果是标准 SQL,在 MySQL 里遇到不兼容的语法,查一下对应的替代写法。FULL OUTER JOIN在 MySQL 里可以用LEFT JOIN UNION RIGHT JOIN来模拟。
4.2 现象:关系代数表达式的结果和预期不一致
原因:关系代数里属性的顺序和名称容易被忽略。投影运算π后面跟的属性列表,顺序不同结果关系的列顺序就不同,虽然集合语义上等价,但对照答案时容易误判。
解决:对照答案时,先看属性集合是否一致,再看元组集合是否一致。顺序问题可以忽略,但属性名和值的对应关系不能错。
4.3 现象:范式分解答案看不懂推导过程
原因:答案往往只给最终分解结果,省略了中间步骤。尤其是涉及属性闭包计算和多属性依赖的题目,跳步很严重。
解决:自己动手算一遍属性闭包。从给定的函数依赖集出发,对每个属性集求闭包,看它能推出哪些属性。这个过程虽然繁琐,但能帮你真正理解分解的逻辑。我一般会在草稿纸上把每一步的闭包都写出来,再和答案对照。
4.4 现象:中文乱码,建表后插入数据变成问号
原因:数据库的字符集没有设置成utf8mb4,或者连接字符集不对。
解决:建库时指定DEFAULT CHARACTER SET utf8mb4,建连接时加上?useUnicode=true&characterEncoding=utf8。如果已经建了库,可以用ALTER DATABASE db_practice CHARACTER SET utf8mb4;修改。
4.5 现象:并发控制题的调度分析结果和答案对不上
原因:可串行化调度的判定需要画优先图,答案可能省略了图的绘制过程,直接给结论。如果优先图里有一条环,那就是不可串行化的,但环的检测容易漏边。
解决:老老实实画优先图。把每个事务的操作按顺序列出来,遇到冲突操作(读写同一数据项且至少一个是写)就画一条有向边。画完后检查有没有环。这一步没有捷径,画图最可靠。
5. 进阶用法:把答案变成自己的题库
5.1 用答案反向出题
这份答案最大的价值不是“对答案”,而是“反向出题”。我习惯把答案遮住,只看题目,自己先做一遍,然后对照答案找差距。更进一步,可以把答案里的 SQL 改一改条件,自己出变体题。比如原题是“查询选修了数据库原理的学生”,你可以改成“查询选修了数据库原理且成绩大于 80 的学生”,然后自己写 SQL 验证。
5.2 建立错题索引
对照答案的过程中,错题是宝贵的。我一般会建一个错题表,记录题号、错误原因、正确思路和涉及的知识点。比如:
| 题号 | 错误类型 | 知识点 | 正确思路 |
|---|---|---|---|
| 3-5 | 关系代数除法漏条件 | 除法运算 | 双重 NOT EXISTS 翻译 |
| 4-2 | SQL 嵌套查询顺序错 | 子查询 | 先内层后外层 |
| 5-8 | 范式判定漏传递依赖 | 3NF | 检查非主属性对码的依赖 |
这张表考前翻一遍,比重新做一遍题还管用。
5.3 用脚本批量验证 SQL 答案
如果答案里的 SQL 题很多,手动一条条跑太慢。可以写个 Python 脚本,把 SQL 语句从文件里读出来,逐条执行并输出结果:
import pymysql # 连接数据库 conn = pymysql.connect( host='localhost', user='root', password='your_password', database='db_practice', charset='utf8mb4' ) cursor = conn.cursor() # 从文件中读取 SQL 语句,按分号分割 with open('sql_answers.sql', 'r', encoding='utf-8') as f: sql_text = f.read() statements = [s.strip() for s in sql_text.split(';') if s.strip()] for i, stmt in enumerate(statements): try: cursor.execute(stmt) results = cursor.fetchall() print(f"第 {i+1} 条执行成功,返回 {len(results)} 行") for row in results: print(row) except Exception as e: print(f"第 {i+1} 条执行失败:{e}") cursor.close() conn.close()这段脚本的逻辑很直接:连接数据库,读取 SQL 文件,按分号拆分语句,逐条执行。charset='utf8mb4'保证中文不乱码。执行失败的语句会打印错误信息,方便定位问题。参数方面,host、user、password和database需要根据你的本地环境修改。
从那以后我每次拿到类似的课后答案资源,都会先建库、跑脚本、画优先图,把能自动化的部分自动化,把不能自动化的部分手动画图验证。这套流程走下来,答案就不再是“别人的答案”,而是变成了自己的知识。希望帮到你。
本文还有配套的精品资源,点击获取