简介:这份《数据库课后习题答案(第四版)》配套资料面向高校数据库课程学习者与备考学生,聚焦SQL Server 2000环境下数据库原理实验的习题解答与操作参考,帮助读者巩固课堂知识、核对实验步骤与结果。资源包内含1个PDF文档,大小约856KB,内容以实验手册形式组织,覆盖服务管理器、企业管理器、查询分析器常用工具的使用,Windows与SQL Server两种身份验证模式的区别,以及CREATE DATABASE、ALTER DATABASE、DROP DATABASE等T-SQL语句的创建、修改与删除数据库操作。资料还涉及主数据文件、次要数据文件与事务日志文件三类文件类型,student、course、sc等表的创建与主键、外键、UNIQUE、CHECK约束应用,以及数据输入与查询例题解析。目前已有1830人学习下载,适合需要对照实验手册查漏补缺、理解数据库对象管理与SQL语句用法的读者参考使用。
1. 数据库课后习题答案(第四版).pdf:从一份答案反推 SQL Server 实操能力
很多人拿到《数据库课后习题答案(第四版).pdf》的第一反应是“对答案”,但我更愿意把它当成一张能力清单来用。数据库这门课,课后习题覆盖的无非是关系代数、SQL 语句、范式分解、事务与并发这几块,而其中真正能在 SQL Server 里跑起来、能验证对错的,只有 SQL 语句和建表约束那部分。换句话说,这份答案里一半是纸面推导,另一半是可以直接丢进 SQL Server 里跑出结果的。如果你正在学数据库、准备课程设计,或者想借课后题把 SQL Server 的增删改查、约束、视图、存储过程练熟,那这份答案的价值不在于“抄”,而在于它给了你一套现成的验证用例。下面我按“怎么把答案变成可执行的练习环境”这条线来讲,从环境搭建到逐类题型落地,再到我踩过的坑,全部给到可复现的步骤。
2. 把答案里的 SQL 题变成 SQL Server 可执行脚本:环境与建库
2.1 为什么选 SQL Server 而不是 SQLite 来验证课后题
课后习题里大量出现CREATE TABLE带外键、CHECK约束、IDENTITY自增列、GROUP BY配合HAVING的写法,这些在 SQLite 里要么语法不同,要么约束行为不一致。比如 SQLite 对ALTER TABLE支持有限,课后题里常见的“给已有表加一列并设默认值”在 SQLite 上会翻车。SQL Server 的 T-SQL 语法和大多数教材(尤其是第四版这类偏 SQL Server / SQL Server 2016 教材)是对齐的,用 SQL Server 跑答案,语法报错基本就是你真的写错了,而不是方言差异。
安装上,SQL Server 2019 或 SQL Server 2022 的 Developer 版就够用,配合 SSMS(SQL Server Management Studio)做查询窗口。如果你机器上已经有 SQL Server 2008,注意它和 SSMS 2022 可以共存,但连接时要用对应版本的驱动。常见做法是:装一个 SQL Server 2019 实例,再装 SSMS 18.x 以上,这样课后题里涉及的窗口函数、OFFSET FETCH都能跑。
提示:安装时实例名建议用默认
MSSQLSERVER,否则后面连接字符串要改,容易在课程设计里埋雷。
2.2 建一个专门跑课后题的数据库和登录账号
不要直接在master里建表,这是血泪经验。课后题的表名往往很通用,比如Student、Course、SC,一旦和别的库重名,后面查错会怀疑人生。先建独立库:
-- 创建课后题专用数据库 CREATE DATABASE DbHomework; GO -- 切换到该库 USE DbHomework; GO -- 创建一个专用登录(可选,方便课程设计演示) CREATE LOGIN hw_user WITH PASSWORD = 'Hw@123456'; GO CREATE USER hw_user FOR LOGIN hw_user; GO ALTER ROLE db_owner ADD MEMBER hw_user; GO逻辑说明:CREATE DATABASE建库,USE切上下文,后面所有建表都在这个库里。CREATE LOGIN是服务器级,CREATE USER是数据库级,两步别搞混。参数上,密码要满足 SQL Server 的复杂度策略,否则会报“密码不符合要求”。如果你只是本地练习,可以跳过登录创建,直接用 Windows 身份验证。
2.3 从答案里提取建表语句并补上约束
课后答案里的建表语句经常省略约束,只给列名和类型。直接抄会丢掉外键和CHECK,导致后面插入脏数据也不报错。我一般会对照题目描述把约束补全。以经典的“学生-课程-选课”为例:
-- 学生表 CREATE TABLE Student ( Sno CHAR(9) PRIMARY KEY, -- 学号主键 Sname NVARCHAR(20) NOT NULL, Ssex NCHAR(1) CHECK (Ssex IN (N'男', N'女')), Sage SMALLINT CHECK (Sage BETWEEN 15 AND 45), Sdept NVARCHAR(20) ); GO -- 课程表 CREATE TABLE Course ( Cno CHAR(4) PRIMARY KEY, Cname NVARCHAR(40) NOT NULL, Cpno CHAR(4) NULL, -- 先修课,自引用外键 Ccredit SMALLINT CHECK (Ccredit > 0), CONSTRAINT FK_Course_Cpno FOREIGN KEY (Cpno) REFERENCES Course(Cno) ); GO -- 选课表 CREATE TABLE SC ( Sno CHAR(9), Cno CHAR(4), Grade SMALLINT CHECK (Grade BETWEEN 0 AND 100), PRIMARY KEY (Sno, Cno), FOREIGN KEY (Sno) REFERENCES Student(Sno), FOREIGN KEY (Cno) REFERENCES Course(Cno) ); GO逻辑说明:Student的Ssex用CHECK限制取值,Sage限制范围,这是课后题常考的“完整性约束”。Course的Cpno自引用外键要注意插入顺序,先插没有先修课的课。SC用复合主键,外键分别指向两张表。参数上,CHAR(9)和NVARCHAR的选择看题目要求,学号定长用CHAR,姓名变长用NVARCHAR避免乱码。
注意:自引用外键插入时,如果先插的课
Cpno指向还没插入的课,会报外键冲突。解决办法是先插Cpno为NULL的课,再UPDATE补上。
3. 按题型逐类落地:增删改查、视图、存储过程怎么对答案
3.1 增删改查题:用答案里的数据验证结果集
课后题里最多的就是“查询选修了 3 号课程的学生姓名”这类。答案给的是 SQL 和预期结果,你要做的是把数据插进去再跑。插入数据时注意顺序:先Student,再Course,最后SC。下面是一组可复现的插入:
-- 插入学生 INSERT INTO Student VALUES ('201215121', N'李勇', N'男', 20, N'CS'), ('201215122', N'刘晨', N'女', 19, N'CS'), ('201215123', N'王敏', N'女', 18, N'MA'); GO -- 插入课程,先插无先修课的 INSERT INTO Course VALUES ('1', N'数据库', NULL, 4); INSERT INTO Course VALUES ('2', N'数学', NULL, 2); INSERT INTO Course VALUES ('3', N'信息系统', '1', 4); GO -- 插入选课 INSERT INTO SC VALUES ('201215121', '1', 92), ('201215121', '2', 85), ('201215122', '1', 90), ('201215123', '3', 88); GO逻辑说明:INSERT INTO ... VALUES多行写法在 SQL Server 2008 以后都支持。Course里'3'的先修课是'1',所以'1'必须先插。SC的Grade在 0-100 之间,符合CHECK。跑完这些,你就可以把答案里的查询语句逐条粘贴执行,对比结果集。如果结果对不上,先看WHERE条件里的字符串有没有加N前缀,中文不加N可能匹配不到。
参数上,CHAR类型比较时会补空格,'1'和'1 '在CHAR(4)里可能被认为相等,这是课后题里容易忽略的坑。如果题目要求精确匹配,建议把课程号改成VARCHAR。
3.2 视图与权限题:把答案里的 GRANT 跑通
第四版教材里视图和权限是重点。答案可能写CREATE VIEW IS_Student AS SELECT ...,然后GRANT SELECT ON IS_Student TO U1。在 SQL Server 里,GRANT需要先有对应的登录和用户。你可以用 2.2 里建的hw_user来测:
-- 创建视图:只显示 CS 系学生 CREATE VIEW CS_Student AS SELECT Sno, Sname, Sage FROM Student WHERE Sdept = N'CS'; GO -- 授权给 hw_user GRANT SELECT ON CS_Student TO hw_user; GO -- 验证:以 hw_user 身份查询(需另开连接) SELECT * FROM CS_Student;逻辑说明:视图把WHERE条件固化,GRANT只给SELECT,不给基表权限,这样hw_user只能看 CS 系学生。参数上,GRANT的权限列表可以是SELECT, INSERT, UPDATE,按题目要求给。如果报“找不到用户”,检查hw_user是否在当前库里有用户映射。
提示:SQL Server 里视图和基表的权限是独立的,授权视图不代表能访问基表,这点和教材一致。
3.3 存储过程与触发器题:用答案逻辑建可调用对象
课后题最后几章常要求写存储过程或触发器。答案给的是逻辑描述,你要翻译成 T-SQL。比如“创建一个存储过程,查询某门课程的平均分”:
CREATE PROCEDURE GetAvgGrade @Cno CHAR(4) AS BEGIN SELECT Cno, AVG(CAST(Grade AS DECIMAL(5,2))) AS AvgGrade FROM SC WHERE Cno = @Cno GROUP BY Cno; END; GO -- 调用 EXEC GetAvgGrade '1';逻辑说明:@Cno是输入参数,CAST把SMALLINT转成小数,否则AVG会截断成整数。GROUP BY Cno保证返回一行。参数上,如果题目要求“没有选课也返回 0”,就要用LEFT JOIN或ISNULL处理。
触发器题类似,注意AFTER INSERT和INSTEAD OF的区别。课后题常考“往SC插入时检查成绩是否合法”,其实CHECK已经做了,触发器更多是考语法。我一般会写一个AFTER INSERT触发器把插入记录写进日志表,验证触发时机。
4. 避坑与排查:跑课后题答案时最容易翻车的 5 个点
4.1 现象:中文显示成问号,原因:没加 N 前缀,解决:字符串前加 N
这是最常见的翻车。答案里写'男',你直接跑,插入后查出来是??。原因是数据库默认排序规则不是中文,VARCHAR存中文会丢。解决:所有中文字符串前加N,列类型用NVARCHAR或NCHAR。如果已经建错表,用ALTER TABLE改列类型,但已有数据可能已经损坏,建议重建。
4.2 现象:外键冲突,原因:插入顺序不对或自引用,解决:先插父表再插子表
SC插入时报“与外键约束冲突”,九成是Student或Course里没有对应主键。自引用外键更隐蔽,Course的Cpno指向自己,必须先插NULL再UPDATE。排查时用SELECT * FROM Student WHERE Sno = '...'确认父记录存在。
4.3 现象:SSL 证书链不受信任,原因:驱动版本和加密设置,解决:加 TrustServerCertificate
连接 SQL Server 时如果报[08001] SSL 提供程序: 证书链是由不受信任的颁发机构颁发的,这是本地自签证书导致的。在连接字符串里加TrustServerCertificate=True,或者在 SSMS 的连接属性里勾选“信任服务器证书”。注意这不是数据库本身的问题,是驱动加密校验。
4.4 现象:GROUP BY报列无效,原因:SELECT 列不在 GROUP BY 里,解决:补聚合或补分组
答案里写SELECT Sno, Cno, AVG(Grade) FROM SC GROUP BY Sno,在 SQL Server 里会报Cno无效,因为Cno既不在GROUP BY也没聚合。这是教材和实际执行的差异,解决办法是按题目语义把Cno加进GROUP BY,或者用MAX(Cno)。别直接关掉ONLY_FULL_GROUP_BY,SQL Server 没这个开关。
4.5 现象:IDENTITY列插入显式值报错,原因:没开IDENTITY_INSERT,解决:临时开启
如果课后题要求给自增列指定值,直接INSERT会报“当 IDENTITY_INSERT 为 OFF 时,不能为表中的标识列插入显式值”。解决:
SET IDENTITY_INSERT Student ON; INSERT INTO Student (Sno, Sname) VALUES ('201215124', N'张三'); SET IDENTITY_INSERT Student OFF;注意一个会话同时只能对一张表开,用完必须关,否则后续插入会乱。
5. 进阶:把课后题答案变成自动化验证脚本
跑通单题之后,我习惯把答案里的查询和预期结果写成断言脚本,这样复习时一键验证。思路是:把预期结果存成临时表,用EXCEPT比对实际结果和预期结果,差集为空就算通过。下面是一个模板:
-- 预期结果 SELECT '201215121' AS Sno, N'李勇' AS Sname INTO #Expected; -- 实际结果 SELECT Sno, Sname INTO #Actual FROM Student WHERE Sdept = N'CS'; -- 比对:两个方向都为空才一致 SELECT * FROM #Expected EXCEPT SELECT * FROM #Actual; SELECT * FROM #Actual EXCEPT SELECT * FROM #Expected; GO逻辑说明:EXCEPT返回第一个结果集有而第二个没有的行,两个方向都空说明完全一致。参数上,临时表用#开头,会话结束自动删。这个方法对SELECT类题目特别有效,对INSERT/UPDATE类题目可以改成比对受影响行数或目标表内容。
我自己的习惯是每做完一章课后题,就把验证脚本存成一个.sql文件,文件名带章节号。下次复习直接打开跑一遍,哪题挂了立刻知道。数据库这东西,看答案看十遍不如自己跑一遍,尤其是约束和事务那块,不亲手触发一次外键冲突,永远记不住插入顺序。希望帮到你。
本文还有配套的精品资源,点击获取