资讯详情

资讯详情

数据库关系代数与SQL实战入门:从课本习题到可执行查询

简介本资源是《数据库系统概论第5版》王珊、萨师煊主编教材的配套课后习题详细答案面向高校计算机、软件工程、信息管理等专业本科生及数据库初学者用于巩固关系模型、关系代数、SQL语言等核心理论知识辅助课程学习与期末备考。文件为单个Word文档.doc共1份大小588KB内容覆盖第2章关系数据库与第3章SQL语言全部重点习题包括关系模型三要素、完整性约束判定、等值连接与自然连接辨析、SPJ关系代数表达式推导、SQL建表与多表查询语句编写等典型题型并附有清晰解题步骤与关键注释。已有1723人学习下载答案严格对应教材章节逻辑术语规范、推导严谨可直接用于作业参考、考前梳理与概念自查是理解关系数据库底层原理与提升SQL实战能力的实用学习材料。1. 别被“数据库系统概论”吓住它不是天书是你手边那本能查、能练、能抄答案的“关系代数练习册”你刚点开这份叫《数据库系统概论第5版答案王珊版》的文档心里可能嘀咕“这名字怎么像大学期末考前夜在打印店狂敲的PDF全是‘关系模型’‘范式’‘参照完整性’……我连SQL SELECT都写不利索看这个有啥用”别急。先说个大实话这份文档根本不是教材也不是讲义它是一份“带解题过程的课后习题标准答案集”——而且是专为零基础初学者设计的“脚手架式答案”。它解决的问题特别具体当你对着课本第二章那道“求供应工程J1零件的供应商号码SNO”的题发懵时它不跟你讲什么叫“投影π”而是直接给你写出πSno(σJno‘J1’SPJ)再一行行翻译成“先从SPJ表里挑出JNOJ1的行这是选择σ再只留下SNO这一列这是投影π”当你被“等值连接和自然连接的区别”绕晕时它用一句话点破“等值连接是‘手动指定用哪个字段相等’自然连接是‘自动找名字相同、类型相同的字段连完还把重复列删掉’——就像你微信加好友输手机号等值和扫对方二维码自动通过自然。”它适合谁适合三类人正在啃王珊《数据库系统概论》第5版、但卡在“关系代数符号看不懂”“SQL嵌套查询写不出来”的本科生准备软考中级数据库系统工程师、想快速过掉“关系理论SQL语法”基础模块的在职人想转行做数据分析或后端开发需要补上“数据库底层逻辑”这一课、但讨厌纯理论空讲的自学者。它不承诺让你一夜成为DBA但它能让你今天下午就搞懂“为什么外码可以为空”“为什么视图不能随便UPDATE”并亲手把课本P42那道SPJ四表联查题跑通。接下来我们就从最扎手的第一关开始不背定义先动手画出你的第一个关系图。2. 先搞懂一个概念关系模型不是抽象理论而是你每天都在用的“Excel多表联动”很多新手一看到“关系模型由关系数据结构、关系操作集合、关系完整性约束三部分组成”就头皮发麻。别急着记这三句话——我们把它拆成你手机里正在用的功能。2.1 关系数据结构就是你熟悉的“表格”但比Excel更较真想象你用Excel管理班级通讯录A列是学号唯一标识一个人B列是姓名C列是班级号。这张表本身就是“关系数据结构”里的一个关系Relation也就是我们常说的“一张表”。表头A/B/C这些列名叫属性Attribute每一行数据叫一个元组Tuple整张表的结构定义比如“学号是2位字符不能为空”叫关系模式Relation Schema。提示课本里说“关系是笛卡尔积的子集”听着玄乎。其实就等于说“这张表的所有行必须是从所有可能组合中筛选出来的合法数据”。比如你班只有30人那这张表就只能有30行不能凭空冒出第31行——这就是“结构”在管事。2.2 关系操作集合不是命令行而是“对表格动手指的5种基本动作”课本第二章开头问“关系代数的基本运算有哪些”答案是并、差、笛卡尔积、投影、选择。别被名字吓退它们对应的是你每天都在做的5件事运算名中文意思类比Excel操作课本例题中的样子白话解释选择σ筛选行CtrlF找“城市天津”σJno‘J1’SPJ“从SPJ表里只留下JNO这一列值等于J1的所有行”投影π提取列只保留A列和C列πSno(σJno‘J1’SPJ)“先把上面筛出来的行再只取SNO这一列”笛卡尔积×两表暴力拼接把表1每行和表2每行配对S × P“S表有3行P表有4行结果就是12行3×4每行是S的一行P的一行”并∪合并去重把两个Sheet的数据粘一起删重复行R ∪ S“把R表和S表的所有行合起来重复的只留一份”差−剔除交集用表1减去表2里有的行R − S“R表里有但S表里没有的那些行”你会发现所有复杂查询都是这5个动作的组合。比如课本P23第6题第4问“求没有使用天津供应商生产的红色零件的工程号JNO”答案是πJno(SPJ) − πJNOσcity‘天津’∧Color‘红‘ S∞SPJ∞P。拆开看先算右边σcity‘天津’∧Color‘红‘ S∞SPJ∞P→ 从S、SPJ、P三表连接结果里找出“城市天津且颜色红”的记录再πJNO→ 只取这些记录的JNO列左边πJno(SPJ)→ 取SPJ表里所有JNO最后“左边减右边” → 所有JNO里去掉那些“被天津红零件污染过”的工程号。这根本不是数学推导而是一套清晰的“数据清洗流水线”。2.3 关系完整性约束不是枷锁而是你建表时自动开启的“防错开关”很多人觉得“完整性约束”是DBA才管的事。错。它其实是你在CREATE TABLE时悄悄按下的几个安全按钮实体完整性主键不能为空、不能重复。就像你填身份证号——系统强制要求你必须填而且全世界不能有两个一样的。课本答“若属性A是基本关系R的主属性则属性A不能取空值”。实操提醒建S表时Sno C(2) UNIQUE这个UNIQUE就是实体完整性的落地。参照完整性外键必须指向真实存在的主键或为空。就像你填“部门编号”系统会检查这个编号在DEPT表里真的存在吗如果不存在就拦住你。课本答“外码属性的值可以为空但前提是它本身不是主属性”。举个生活例子你填简历“曾任职公司”这一栏可以空着没工作过但“身份证号”不能空它是你的主键。用户定义完整性你自定义的业务规则。比如“职工年龄不得超过60岁”课本P127第6题里用CONSTRAINT C1 CHECK (Age60)实现。这相当于在Excel单元格里设“数据验证”只允许输入0-60的数字超了就弹窗报错。这三类约束本质是同一套逻辑用声明式规则代替人工校验。你不用每次INSERT前自己写代码检查“这个SNO在S表里有没有”数据库替你做了。2.4 避坑新手写关系代数和建表时最容易翻车的5个地方现象 → 原因 → 解决一条一条来全是血泪经验现象用关系代数写“求供应红色零件的供应商”时写了πSno(σCOLOR‘红’P)结果查出来一堆空。原因P表里只有零件信息PNO, PNAME, COLOR没有供应商SNO你漏掉了SPJ表这个“桥梁”。解决牢记“供应商→零件”不是直连中间必须过SPJ表。正确写法是πSno(σCOLOR‘红’P∞SPJ)先让P和SPJ连接再筛选红色。现象SQL建表时复制课本答案CREATE TABLE S ( Sno C(2) UNIQUESname C(6) Status C(2)CityC(4))执行报错“Unknown data type C”。原因课本用的是教学简化语法C代表Character真实数据库MySQL/PostgreSQL不认。解决把C(2)改成CHAR(2)C(6)改成VARCHAR(6)。这是新手第一道坎跨过去就海阔天空。现象写完SELECT * FROM SPJ,P WHERE SPJ.PNOP.PNO结果行数爆炸比如SPJ有100行P有10行结果1000行。原因忘了加WHERE条件导致笛卡尔积全量生成。课本P58第3题第4问就踩这个坑。解决永远检查JOIN条件是否写全。用EXPLAINMySQL或EXPLAIN QUERY PLANSQLite看执行计划如果显示“CROSS JOIN”立刻回头补ON。现象给视图VSP插入数据INSERT INTO VSP VALUES(S1,P1,100)报错“Cant insert into a view”。原因课本P79明确说“基本表的行列子集视图一般是可更新的”但VSP是SELECT SNO,SPJ.PNO,QTY FROM SPJ,J WHERE ...—— 它涉及JOIN和WHERE属于不可更新视图。解决视图只用来查增删改必须操作底层SPJ表。这是原则不是bug。现象执行UPDATE P SET COLOR蓝 WHERE COLOR红后发现有些红色零件没变蓝。原因字符串比较区分大小写或空格。课本答案写COLOR红但实际数据可能是红 带空格或RED英文。解决先用SELECT COLOR, LENGTH(COLOR) FROM P WHERE COLOR LIKE %红%查真实存储格式再针对性UPDATE。宁可多查一次别信眼缘。3. 先跑通第一个SQL用课本SPJ四表5分钟写出你的第一条“真正能执行”的查询光看关系代数符号还是虚的。现在我们用真实数据库推荐SQLite免安装单文件把课本P42第6题的查询跑通。目标不抄答案自己从建表开始到查出结果全程可复现。3.1 第一步创建四张表照着课本答案改但要改对数据类型打开SQLite命令行或DBeaver/VS Code SQLite插件逐条执行-- 创建S表供应商注意把课本的C(2)改成TEXTUNIQUE保留 CREATE TABLE S ( Sno TEXT UNIQUE, Sname TEXT, Status TEXT, City TEXT ); -- 创建P表零件同理C(2)→TEXTINT保持不变 CREATE TABLE P ( Pno TEXT UNIQUE, Pname TEXT, Color TEXT, Weight INT ); -- 创建J表工程项目 CREATE TABLE J ( Jno TEXT UNIQUE, Jname TEXT, City TEXT ); -- 创建SPJ表供应情况注意这里没有UNIQUE因为(Sno,Pno,Jno)联合主键 CREATE TABLE SPJ ( Sno TEXT, Pno TEXT, Jno TEXT, Qty INT, -- 联合主键防止重复供应记录 PRIMARY KEY (Sno, Pno, Jno) );为什么用TEXT不用CHAR因为现代数据库对变长字符串更友好且避免CHAR(2)存J1时自动补空格导致匹配失败。这是课本没写的实战细节。3.2 第二步插入课本示例数据最小可行集只插够验证第6题前两问的数据-- 插入S表数据供应商 INSERT INTO S VALUES (S1, 精益, 20, 天津); INSERT INTO S VALUES (S2, 盛锡, 10, 北京); INSERT INTO S VALUES (S3, 东方, 30, 上海); -- 插入P表数据零件 INSERT INTO P VALUES (P1, 螺母, 红, 12); INSERT INTO P VALUES (P2, 螺栓, 绿, 17); INSERT INTO P VALUES (P3, 螺丝, 红, 14); -- 插入J表数据工程 INSERT INTO J VALUES (J1, 三建, 北京); INSERT INTO J VALUES (J2, 一汽, 长春); INSERT INTO J VALUES (J3, 船舶, 上海); -- 插入SPJ表数据供应关系 INSERT INTO SPJ VALUES (S1, P1, J1, 200); INSERT INTO SPJ VALUES (S1, P2, J1, 100); INSERT INTO SPJ VALUES (S2, P1, J2, 300); INSERT INTO SPJ VALUES (S2, P3, J3, 400); INSERT INTO SPJ VALUES (S3, P1, J1, 500);关键点INSERT INTO SPJ VALUES‘ S2’‘ J6’‘ P4’200这种课本答案里的空格‘ S2’是典型陷阱务必删掉否则WHERE S2 S2永远为假。3.3 第三步执行课本P42第6题第1问最简单起点题目“求供应工程J1零件的供应商号码SNO”课本答案SELECT DIST SNO FROM SPJ WHERE JNOJ1注课本笔误DIST应为DISTINCT-- 执行查询注意DISTINCT不是DIST SELECT DISTINCT SNO FROM SPJ WHERE JNOJ1;预期结果SNO --- S1 S3为什么是S1和S3因为SPJ表里有两条JNOJ1的记录(S1,P1,J1)和(S3,P1,J1)。DISTINCT去重所以S1只出现一次。3.4 第四步升级挑战——课本第3问带JOIN的查询题目“求供应工程J1零件为红色的供应商号码SNO”课本答案SELECT SNO FROM SPJ,P WHERE JNOJ1 AND SPJ.PNOP.PNO AND COLOR红-- 执行注意表别名让语句更清晰 SELECT DISTINCT SPJ.SNO FROM SPJ JOIN P ON SPJ.PNO P.PNO WHERE SPJ.JNO J1 AND P.Color 红;预期结果SNO --- S1 S3解释SPJ表里JNOJ1的记录有(S1,P1,J1)和(S3,P1,J1)P表里Color红的有P1和P3JOIN后只有P1能匹配上所以S1和S3都供应了红色零件P1。这就是“连接”的威力——它自动把分散在不同表里的信息缝合起来。3.5 第五步验证课本第5问最难的“除运算”题目“求至少用了供应商S1所供应的全部零件的工程号JNO”课本答案分两步A.SELECT DISTINCT PNO FROM SPJ WHERE SNOS1→ 得到(S1供应的零件P1,P2)B.SELECT JNO FROM SPJ WHERE PNOP1 AND JNO IN (SELECT JNO FROM SPJ WHERE PNOP2)我们直接执行B步A步结果已知-- 找出既用了P1又用了P2的工程号 SELECT DISTINCT JNO FROM SPJ WHERE PNO P1 AND JNO IN ( SELECT JNO FROM SPJ WHERE PNO P2 );预期结果JNO --- J1为什么是J1因为SPJ表里J1用了P1(S1,P1,J1)和P2(S1,P2,J1)J2只用了P1(S2,P1,J2)没用P2J3只用了P3。所以只有J1满足“S1供应的所有零件P1,P2它都用了”。恭喜你刚刚用真实SQL跑通了课本前三道核心查询。这不是死记硬背而是亲手验证了“关系代数→SQL→真实数据”的完整链条。4. 别再死磕“范式”用一张表的演变看懂1NF、2NF、3NF到底在解决什么问题第六章的“函数依赖”“BCNF”“多值依赖”是新手最大心理障碍。课本定义密密麻麻但它的出发点特别朴素怎么设计一张表让它不容易存错、改错、删错数据我们用一个真实场景来演示。4.1 从“一张大杂烩表”开始原始需求与它的灾难假设你要建一张“学生选课成绩表”老板说“就一张表包含所有信息” 你可能这样设计学号姓名系名系主任课程号课程名成绩001张三计算机王教授C001数据库85001张三计算机王教授C002操作系统92002李四数学陈教授C001数据库78问题立刻爆发数据冗余张三的系名、系主任重复存了2次李四的系名、系主任也重复。如果王教授退休了你得改2行更新异常想把“计算机系”主任改成“李教授”漏改一行数据就自相矛盾删除异常如果张三退学了删掉他所有选课记录系主任信息也跟着消失了插入异常新成立一个“人工智能系”还没招学生你无法插入系信息因为学号不能为空。这就是未规范化的表0NF——所有字段挤在一起毫无结构。4.2 拆成两张表解决冗余进入1NF和2NF第一步把“学生基本信息”和“选课成绩”分开学生表Student学号姓名系名001张三计算机002李四数学选课表SC学号课程号成绩001C00185001C00292002C00178现在满足1NF了吗课本定义“每一个分量是不可再分的数据项”。是的——学号是原子值不是“001,002”这种列表成绩是数字没有逗号分隔的多值。✅但还有问题系名→系主任的依赖没解决。在Student表里“系名”决定“系主任”计算机系→王教授但“系名”不是主键学号才是这就是部分函数依赖非主属性系主任依赖于主键的一部分系名而不是整个主键学号。解决方案再拆系表Department| 系名 | 系主任 |学生表Student| 学号 | 姓名 | 系名 |系名变成外键此时Student表主键是学号所有非主属性姓名、系名都完全依赖于学号系名作为外键指向Department表。这就消除了部分依赖达到2NF。4.3 再拆一次解决传递依赖进入3NF现在Student表里还有隐患如果“系名”变了比如“计算机系”改名“智能科学系”你得改Student表里所有相关行。更好的方式是用“系号”作主键系表Department系号系名系主任D01计算机王教授D02数学陈教授学生表Student学号姓名系号001张三D01002李四D02为什么这是3NF课本定义“不存在非主属性对码的传递函数依赖”。Student表主键是学号非主属性是姓名、系号姓名完全依赖学号没问题系号完全依赖学号没问题系号→系主任的依赖在Department表里不经过Student表传递。所以所有依赖都是“直接”的没有“学号→系号→系主任”这种链条。✅这就是3NF的核心让每个表只负责一件事且所有信息都直接由主键决定。不是炫技是防错。4.4 避坑范式学习中最常见的3个误解误解“范式越高越好必须做到BCNF”。真相BCNF会过度拆分导致大量JOIN影响性能。实际项目中3NF是黄金标准。课本P152第7题说“各关系模式都只有一个码……所以属于BCNF”那是教学简化真实业务表很少追求BCNF。误解“1NF就是不能有重复列”。真相1NF的关键是“原子性”。比如“电话”字段存“1381234,1395678”就是违反1NF逗号分隔多值但存JSON字符串{mobile:138****1234,work:010-12345678}只要数据库把它当一个不可分割的字符串就符合1NF。误解“函数依赖X→Y必须Y的值由X计算得出”。真相函数依赖是业务规则不是数学公式。比如“身份证号→姓名”不是用身份证号算出姓名而是业务上规定同一个身份证号永远对应同一个人名。这是语义约束不是算法。5. 下一步学什么从“抄答案”到“自己出题”我的3步渐进路线你已经能读懂课本答案、能建表、能跑通SPJ查询、能理解范式背后的防错逻辑。下一步不是去啃《数据库系统实现》而是把这份答案集变成你的“肌肉记忆训练器”。我第一次学的时候也是从这份答案起步后来带新人发现真正的入门门槛不在知识深度而在“敢不敢把课本题当成真实需求来解”。以下是我亲测有效的3步法每一步都对应一个具体动作5.1 第一步把课本习题当“需求文档”重写SQL重点练“翻译能力”不要满足于看懂答案。拿出纸笔把课本P42第6题当成产品经理给你的需求“老板要查所有供应‘三建’工程的供应商以及他们供应的零件颜色和重量。”你的任务① 识别涉及哪些表SPJ、J、P、S② 识别过滤条件J.JNAME三建③ 识别要查的字段S.SNO, P.Color, P.Weight④ 写出JOIN路径SPJ→J找工程SPJ→P找零件⑤ 最后写出完整SQL不看答案。做完后对照课本P59第4题第9问的答案SELECT S.SNO, P.Color, P.Weight FROM SPJ,J,P,S WHERE SPJ.JNOJ.JNO AND SPJ.PNOP.PNO AND SPJ.SNOS.SNO AND J.JNAME三建。差距在哪是少写了某个JOIN条件还是字段名写错了表前缀把这些错误记在本子上下次同类题自动预警。5.2 第二步给答案“挑刺”尝试优化重点练“工程思维”课本答案是教学导向不是性能导向。比如P59第4题第4问“求没有使用天津供应商生产的红色零件的工程号JNO”课本答案SELECT DISTINCT JNO FROM SPJ WHERE JNO NOT IN (SELECT JNO FROM SPJ,P,S WHERE S.CITY天津 AND P.COLOR红 AND S.SNOSPJ.SNO AND P.PNOSPJ.PNO)这个NOT IN在大数据量下会很慢。你的任务① 用LEFT JOIN IS NULL重写更高效SELECT DISTINCT SPJ.JNO FROM SPJ LEFT JOIN ( SELECT SPJ2.JNO FROM SPJ SPJ2 JOIN S ON SPJ2.SNO S.SNO JOIN P ON SPJ2.PNO P.PNO WHERE S.City 天津 AND P.Color 红 ) AS bad_jno ON SPJ.JNO bad_jno.JNO WHERE bad_jno.JNO IS NULL;② 思考为什么这个更快因为NOT IN遇到NULL会返回空结果而LEFT JOIN逻辑更确定。这不是炫技是培养“数据量意识”——你写的SQL未来可能跑在百万级数据上。5.3 第三步反向出题给自己挖坑重点练“设计能力”合上答案打开空白文档做这件事① 选一个现实场景比如“图书馆借阅系统”② 设计3张表Book书号、书名、作者、Reader读者号、姓名、单位、Borrow读者号、书号、借期、还期③ 给自己出3道题Q1查所有“计算机类”书籍的借阅次数需JOIN Book和BorrowQ2查从未借过书的读者用NOT EXISTS或LEFT JOINQ3查借阅过《数据库系统概论》且还期超过30天的读者需日期计算。④ 写出答案再用SQLite建表、插测试数据、验证。从“解题者”变成“出题者”你就真正入门了。因为出题要思考数据怎么组织范式、查询怎么关联JOIN、边界怎么处理NULL、空集。这比刷100道题都管用。从那以后我每次拿到新业务需求都强制走一遍这个流程先画ER图哪怕就3个框再想清楚主外键最后才写第一行SQL。不是为了显得专业而是因为跳过这三步写的代码90%会在上线后半夜把你叫醒。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →