☰
数据库系统概论答案文档:SQL与关系代数实战解析
2026/10/27 3:16:20 网站建设 项目流程

简介:这份文档是《数据库系统概论》第五版(王珊版)的课后习题参考答案,面向高校计算机及相关专业学生、考研复习者与数据库入门自学者,用于对照教材章节核对习题思路、巩固关系数据库基础理论。压缩包内共1个doc文件,约588KB,按教材章节组织答案,覆盖关系模型三要素、关系数据语言分类、实体完整性与参照完整性规则、关系代数五种基本运算及交连接除的推导,以及SQL语言特点、建表语句与SPJ数据库查询等典型题目,并附有等值连接与自然连接区别等概念辨析。已有1724人学习下载,适合课后对答案、期末梳理考点或作为习题课参考,帮助读者在关系代数表达式书写与SQL查询转换上查漏补缺。

1. 一份被低估的“答案文档”:它到底能解决什么

期末周翻数据库,最怕的不是概念多,而是题做了不知道对错。这份《数据库系统概论》第 5 版(王珊版)答案文档,覆盖第 2 章到第 7 章,从关系模型、关系代数、SQL 语言,一路到安全性、完整性、关系理论和数据库设计。它不是教材替代品,而是一份“对照答案 + 解题过程”的复盘材料:关系代数题给了完整表达式,SQL 题给了可执行语句,范式题给了函数依赖推导。适合三类人:正在跟课、需要核对课后习题的在校生;准备复试或笔试、想快速过一遍经典题型的求职者;以及带课、需要一份现成习题参考的助教。下面按“怎么读、怎么用、哪里会翻车”拆开讲。

2. 关系代数与 SQL 对照:把第 2、3 章的题真正跑通

2.1 先看关系代数表达式,再落到 SQL

第 2 章习题 6 的 SPJ 数据库是整份文档的核心案例,S(供应商)、P(零件)、J(工程)、SPJ(供应情况)四张表贯穿前后。文档给出的关系代数答案,比如“求供应工程 J1 零件的供应商号码”写成 πSno(σJno='J1'(SPJ)),这是标准的投影加选择。很多人看答案觉得懂了,一写 SQL 就卡住,原因是没有把代数符号和 SQL 子句建立映射。我的习惯是先手写代数式,再逐符号翻译:π 对应 SELECT 后的列,σ 对应 WHERE,∞ 对应 JOIN,÷ 对应 NOT EXISTS 双层嵌套。这样第 3 章那些 SQL 答案就不是背出来的,而是推出来的。

以“求没有使用天津供应商生产的红色零件的工程号”为例,文档给的是差集思路:全部工程号减去用了天津红色零件的工程号。落到 SQL 就是:

-- 全部工程号 减去 使用了天津供应商红色零件的工程号 SELECT DISTINCT JNO FROM J WHERE JNO NOT IN ( SELECT SPJ.JNO FROM SPJ JOIN S ON S.SNO = SPJ.SNO JOIN P ON P.PNO = SPJ.PNO WHERE S.CITY = '天津' AND P.COLOR = '红' );

这段的关键在 NOT IN 子查询里三表连接的条件顺序:先按 SNO 关联供应商拿到城市,再按 PNO 关联零件拿到颜色,两个过滤条件必须同时成立才算“用了天津的红色零件”。参数上要注意 CITY 和 COLOR 是字符型,单引号不能省;如果子查询结果里出现 NULL,NOT IN 会整体返回空集,这是 SQL 三值逻辑的经典坑,后面避坑章节会展开。

2.2 除法运算:文档里最容易看漏的一题

第 2 章习题 6 第 5 问“求至少用了供应商 S1 所供应的全部零件的工程号”,文档用除法 πJno,Pno(SPJ) ÷ πPno(σSno='S1'(SPJ)) 表达。除法是关系代数里最抽象的一个,直接照抄符号没法执行。文档在第 3 章给了一个“分两步”的 VFP 写法,先查 S1 供应的零件号,再查同时用了这些零件的工程。这个思路可以改写成标准 SQL 的 NOT EXISTS 双重否定:

-- 不存在一个 S1 供应的零件,该工程没有使用 SELECT DISTINCT JNO FROM SPJ AS X WHERE NOT EXISTS ( SELECT * FROM SPJ AS Y WHERE Y.SNO = 'S1' AND NOT EXISTS ( SELECT * FROM SPJ AS Z WHERE Z.JNO = X.JNO AND Z.PNO = Y.PNO ) );

逻辑说明:外层遍历每个工程,中层遍历 S1 供应的每个零件,内层检查该工程是否用了这个零件。两层 NOT EXISTS 合起来就是“没有哪个 S1 零件是这个工程没用过的”,等价于“用了 S1 的全部零件”。参数上 SNO='S1' 是硬编码的供应商标识,换供应商只改这一处;别名 X、Y、Z 不能省,否则内外层同表引用会歧义。这题是笔试高频,能默写出这个结构,除法和 NOT EXISTS 的对应关系基本就通了。

2.3 建表语句里的类型选择要留个心眼

文档第 3 章习题 4 给的建表语句用了 C(2)、C(6) 这种 VFP 风格的类型写法,比如CREATE TABLE S (Sno C(2) UNIQUE, Sname C(6), Status C(2), City C(4))。这在标准 SQL 里跑不通,C 不是通用类型。实际复现时我一般换成 VARCHAR 或 CHAR:

CREATE TABLE S ( Sno CHAR(2) PRIMARY KEY, Sname VARCHAR(20), Status INT, City VARCHAR(20) ); CREATE TABLE SPJ ( Sno CHAR(2), Pno CHAR(2), Jno CHAR(2), Qty INT, PRIMARY KEY (Sno, Pno, Jno), FOREIGN KEY (Sno) REFERENCES S(Sno), FOREIGN KEY (Pno) REFERENCES P(Pno), FOREIGN KEY (Jno) REFERENCES J(Jno) );

这里有两个改动值得说:一是把 UNIQUE 换成 PRIMARY KEY,因为 Sno 本来就是主码,UNIQUE 只保证唯一不保证非空;二是 SPJ 表补了复合主键和外键,文档原答案只写了字段没写约束,直接建表会缺参照完整性,后面做删除更新题时行为对不上。字段长度也别照抄 C(6),中文姓名六个字符在 VARCHAR 里要按实际编码留余量,我一般给到 20。

3. 安全性与完整性:GRANT、REVOKE 和约束定义怎么落地

3.1 授权语句的粒度与回收的连锁反应

第 4 章习题 7 集中练 GRANT 和 REVOKE,文档给的答案覆盖了表级、列级、行级三种粒度。列级授权如GRANT SELECT, UPDATE(工资) ON 职工 TO 刘星,只放开工资列的更新,其他列仍不可写,这是最小权限原则的直接体现。行级授权GRANT SELECT ON 职工 WHEN USER()=NAME TO ALL依赖 DBMS 对谓词的支持,不是所有产品都认这个语法,复现时如果报错,说明当前环境不支持行级 GRANT,得改用视图加授权的方式绕。

回收语句里最容易被忽略的是 CASCADE。文档在 REVOKE 示例中写了REVOKE INSERT ON Student FROM 王平 CASCADE,CASCADE 的作用是级联收回:如果王平把权限转授给了别人,那些下游权限一并失效。不带 CASCADE 时,若存在转授,语句会直接报错拒绝执行。这个差异在考试里常考,实操里也常翻车——生产环境回收权限忘了 CASCADE,结果报错卡住,或者反过来误用 CASCADE 把一整条授权链全断了。我的做法是回收前先查权限视图确认有没有下游转授,再决定带不带。

3.2 完整性约束:CHECK 和 FOREIGN KEY 的写法差异

第 5 章习题 6 要求给职工表定义主码、参照完整性和“年龄不超过 60”的检查约束。文档答案里CONSTRAINT C1 CHECK (Aage<=60)有个明显的笔误,Aage 应为 Age,而且PRIMARY KEY被拼成了RIMARY KEY。这类 OCR 或录入错误在答案文档里不少,照抄必报语法错。修正后的写法:

CREATE TABLE DEPT ( Deptno NUMBER(2) PRIMARY KEY, Deptname VARCHAR(10), Manager VARCHAR(10), Phone CHAR(12) ); CREATE TABLE EMP ( Empno NUMBER(4) PRIMARY KEY, Ename VARCHAR(10), Age NUMBER(2) CHECK (Age <= 60), Job VARCHAR(9), Sal NUMBER(7,2), Deptno NUMBER(2), CONSTRAINT FK_DEPTNO FOREIGN KEY (Deptno) REFERENCES DEPT(Deptno) );

参数说明:CHECK (Age <= 60) 是列级约束,插入或更新时逐行校验;FOREIGN KEY 默认行为是 RESTRICT,即被参照表还有引用时不允许删除父行。文档第 5 章第 5 题专门讨论了级联删除 CASCADE、受限删除 RESTRICTED、置空 NULLIFIES 三种策略,实际建表时如果不显式写 ON DELETE CASCADE,默认就是受限,删除部门前必须先处理职工记录,否则报外键冲突。这一点在做第 3 章删除题时直接影响结果,文档的 DELETE 答案分两步先删 SPJ 再删 S,正是手动模拟了级联顺序。

3.3 视图授权:把列级权限包进视图

第 4 章习题 7 第 g 问要求“杨兰能看每个部门最高、最低、平均工资,但不能看个人工资”。文档的解法是建一个聚合视图再授权:

CREATE VIEW 部门工资 AS SELECT 部门.名称, MAX(工资) AS 最高, MIN(工资) AS 最低, AVG(工资) AS 平均 FROM 职工 JOIN 部门 ON 职工.部门号 = 部门.部门号 GROUP BY 部门.名称; GRANT SELECT ON 部门工资 TO 杨兰;

这个套路的精髓在于:视图本身不存数据,授权只作用在视图上,底层职工表的明细对杨兰不可见。参数上 GROUP BY 必须包含所有非聚合列,否则标准 SQL 报错;聚合列起别名是为了授权后查询结果可读。注意视图的可更新性——含聚合函数的视图不可更新,文档第 3 章第 8 题也强调了这一点,所以这个视图只能查不能改,正好符合“只读工资统计”的语义。

4. 范式判定与 E-R 转换:第 6、7 章的推导怎么自查

4.1 函数依赖集先写全,再判范式

第 6 章习题 2 给了一个系、学生、班级、学会的场景,要求写出每个关系模式的极小函数依赖集并判范式。文档的推导路径是:先列属性,再根据语义写依赖,然后找候选码,最后逐级判 1NF 到 BCNF。以学生模式 S(Sno, Sname, Sbirth, Dept, Class, Rno) 为例,文档给出的依赖是 Sno→Sname、Sno→Sbirth、Sno→Class、Class→Dept、Dept→Rno,并指出 Sno 与 Rno 之间存在传递依赖。判 3NF 的关键就是找这种“非主属性经由另一个非主属性传递依赖于码”的链条。

自查方法我一般用三步:第一步确认候选码,Sno 能推出所有属性,所以 Sno 是码;第二步看有没有非主属性部分依赖码,单属性码不存在部分依赖,所以至少是 2NF;第三步看有没有传递依赖,Sno→Class→Dept→Rno 这条链上 Dept 和 Rno 都是非主属性,传递依赖成立,所以不是 3NF。文档的结论与此一致。这套三步法对第 6 章第 7 题那些“二目关系是否属于 3NF/BCNF”的判断题同样适用:二目关系只有两个属性,不存在非主属性传递链,所以必是 BCNF,文档给的证明也是这个思路。

4.2 E-R 图转关系模型:联系类型决定外码位置

第 7 章习题 7 的学校概念模型涉及系、班级、教研室、学生、课程、教员六类实体,以及“选修”这个带属性的联系。文档给的转换结果是七张表,其中学生表带了“导师职工号”作为外码,选修表独立成表带“成绩”属性。这里有两个转换规则要记牢:一对多联系把“一”端的主码放到“多”端做外码,比如班级到系,系编号进班级表;多对多联系必须独立建表,主码是两端主码的组合,联系的属性也放这张表里,选修就是典型。

习题 8 的工厂场景更复杂,产品、零件、材料、仓库四类实体,产品组成、零件制造、零件存储、材料存放四个联系,文档转换出七张表。容易出错的是“零件存储”和“材料存放”这两个联系——零件按所属产品分别放仓库,材料按类别放仓库,都是多对多,必须各自独立成表,不能合并。转换完自查一遍:每个多对多联系是否都有独立表、每个一对多联系的外码是否放在多端、联系自身的属性是否跟着联系表走。三条都过,关系模型基本不会漏。

5. 避坑清单:这份答案文档的五个高频翻车点

5.1 现象:照抄建表语句报语法错;原因:VFP 方言混入标准 SQL;解决:类型统一换 VARCHAR/INT

文档第 3 章的建表答案用了 C(2)、C(6) 这类 VFP 类型写法,还有PRIMARY KEY拼写残缺、Aage这种字段名笔误。直接复制到 MySQL 或 PostgreSQL 必然报错。解决方式是先扫一遍语句,把所有 C(n) 换成 VARCHAR(n) 或 CHAR(n),数字型统一 INT 或 NUMBER,主键约束补全拼写。我一般会把整章的建表语句集中改一遍再执行,避免边跑边改打断思路。

5.2 现象:NOT IN 子查询返回空结果;原因:子查询结果含 NULL;解决:改 NOT EXISTS 或加 IS NOT NULL 过滤

第 3 章“没有使用天津供应商零件”那题,如果 SPJ 表里 SNO 或 PNO 存在空值,NOT IN 的三值逻辑会让整个条件判为 UNKNOWN,查询返回空集,看起来像答案错了。根因是 NOT IN 等价于对每个值做“不等于”比较,遇到 NULL 就短路。解决方式有两种:子查询里加WHERE SPJ.JNO IS NOT NULL,或者整体改写成 NOT EXISTS 相关子查询,后者对 NULL 更宽容。这个坑在真实业务查询里同样常见,血泪经验是涉及 NOT IN 的题先查一遍字段可空性。

5.3 现象:删除父表记录报外键冲突;原因:默认 RESTRICT 未设级联;解决:按依赖顺序删或显式声明 ON DELETE CASCADE

第 3 章删除供应商 S2 的答案分两步,先删 SPJ 再删 S,这其实是在手动模拟级联删除。如果建表时没写 ON DELETE CASCADE,直接删 S 表记录会被外键约束拦下。解决方式:要么按文档的两步顺序执行,要么建表时给外键加ON DELETE CASCADE让数据库自动处理。注意级联删除有风险,生产环境删父行会连带删子行,我一般先 SELECT 确认影响范围再执行 DELETE。

5.4 现象:GRANT 行级授权报错;原因:DBMS 不支持 WHEN 谓词;解决:改用视图加表级授权

第 4 章“每个职工只对自己的记录有 SELECT 权力”用了GRANT SELECT ON 职工 WHEN USER()=NAME TO ALL,这个 WHEN 子句不是标准 SQL,多数开源数据库不认。替代方案是建一个带WHERE 姓名 = CURRENT_USER的视图,再对视图授权。这样权限控制逻辑落在视图定义里,兼容性更好。踩过这个坑之后,我遇到行级权限需求一律先想视图,不赌 DBMS 的方言支持。

5.5 现象:范式判断题结论对但推导被扣分;原因:只写结论没写依赖链;解决:按“候选码→部分依赖→传递依赖”三步写全

第 6 章的范式判定题,文档答案有时只给结论,比如“二目关系必是 BCNF”直接给证明框架。自己作答时如果只抄结论,过程分拿不到。正确做法是把候选码怎么来的、部分依赖为什么不成立、传递依赖链具体是哪条,一步步写出来。我习惯在草稿上先画属性依赖图,再按三步法誊写,这样即使结论有偏差,推导过程也能拿分。

6. 把答案文档变成自测工具:一个可复用的验证习惯

答案文档最大的价值不是“对答案”,而是“反向出题”。我的用法是:遮住答案,先按章节自己写一遍,再逐题比对,重点看差异出在哪一步——是关系代数符号写错,还是 SQL 的 WHERE 条件漏了连接,还是范式推导跳了步骤。比对完之后,把错题对应的知识点回填到一张自测表里,按章节和题型两维记录,考前只看这张表。

具体操作上,我会把第 2、3 章的 SPJ 案例完整建库跑一遍,用文档里的查询答案当预期结果,自己写的 SQL 当实际结果,两边对不上就逐行排查。建库脚本可以这样组织:

-- 建库后插入最小测试数据,用于验证查询答案 INSERT INTO S VALUES ('S1','精益','20','天津'); INSERT INTO S VALUES ('S2','盛锡','10','北京'); INSERT INTO P VALUES ('P1','螺母','红',12); INSERT INTO P VALUES ('P2','螺栓','绿',17); INSERT INTO J VALUES ('J1','三建','北京'); INSERT INTO SPJ VALUES ('S1','P1','J1',200); INSERT INTO SPJ VALUES ('S2','P2','J1',100);

数据不用多,每张表两三行就够触发各种查询分支。比如验证“供应 J1 红色零件的供应商”,P1 是红色且被 S1 供应给 J1,预期结果就是 S1;再插一条 S2 供应 P2(绿色)给 J1 的记录,确认查询不会误把 S2 带出来。这种最小数据集的好处是结果可肉眼核对,不用依赖文档给的文字答案。

还有一个习惯值得坚持:每做完一章,把文档里出现的所有 SQL 语句按“查询、更新、授权、约束”四类归档,查询类重点看连接条件和子查询嵌套层数,更新类重点看 WHERE 范围是否精确,授权类重点看 WITH GRANT OPTION 和 CASCADE 的搭配,约束类重点看 CHECK 和 FOREIGN KEY 的触发时机。归档完再回头做第 6、7 章的理论题,会发现很多判定规则其实在 SQL 执行时已经验证过了,理论和实操是同一套逻辑的两面。

从那以后我每次拿到这类答案文档,都强制自己先跑通一个最小案例再往下读,因为光看答案产生的“懂了”是假的,跑通一次才算数。希望这份拆解帮到你,少走几道弯路。

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

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

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

立即咨询