数据库实验五通关指南:从建表约束到事务权限的完整链路自测

发布时间:2026/10/31 2:28:33
数据库实验五通关指南:从建表约束到事务权限的完整链路自测

简介:这份资源是西北工业大学软件学院数据库课程的实验五配套材料,面向正在学习数据库设计、需要完成E-Commerce项目ER建模的学生。内容围绕电商项目说明中的完整ER模式设计展开,包含概念数据模型文件、实验结果图示与文字说明,可帮助读者对照理解实体关系建模的完整流程与规范表达。压缩包共20个文件,以14个gif操作截图、2个txt与2个doc实验文档、1个cdm概念模型文件及1个htm说明页为主,截图直观呈现注册、购物车、结算、订单确认等业务流程,文档则给出实验要求与结果整理,整体约282KB,体积轻便便于随课程资料一并保存。目前已有911人学习下载,适合需要参考ER图绘制思路、核对实验结论或补做建模练习的软件学院学生使用。

1. 数据库实验五到底在练什么:一张地图先看清

很多人复习数据库实验时,最容易犯的错是把每个实验当成孤立任务:实验一建表、实验二写查询、实验三做视图、实验四写存储过程,到了实验五就不知道该往哪接。其实数据库实验是一条完整的能力链,实验五通常落在“综合应用”这一段——它不再考你单个语法会不会,而是考你能不能在多表、多约束、多角色的场景下把前面所有零件组装起来跑通。这份来自某高校软件学院数据库课程的实验五资料,价值不在于给你一个标准答案,而在于它把“建表—约束—查询—事务—权限”这条主线压缩进一个可复现的工程里。如果你正在系统学数据库,或者考前想快速把零散知识串成体系,先别急着抄 SQL,把这张地图看懂:实验五考的是“设计+实现+验证”三件事,缺一件都算没做完。

2. 实验五的知识骨架:从需求到可运行脚本

2.1 需求拆解:先画实体再落表

实验五的起点不是写 SQL,而是把一段自然语言需求翻译成实体和关系。梳理下来会发现,大多数翻车都发生在这一步:需求里说“一个学生可以选多门课,一门课可以被多个学生选”,有人直接建三张表却忘了选课表上的联合主键,结果插入重复选课记录时数据库一声不吭。正确的做法是先列实体清单,再标基数,最后才决定表结构。

需求描述实体/关系落表方式关键约束
学生属于某个班级学生、班级学生表带班级外键外键非空
学生选课学生-课程多对多独立选课表联合主键(学号,课程号)
课程有先修课课程自关联先修关系表双外键均指向课程表
教师授课教师-课程一对多课程表带教师外键外键可空表示待安排

这张表不是让你背,而是提醒你:每一条需求都要能对应到一个约束,约束落不下去,后面查询和事务全是空中楼阁。实验五的评分点往往就藏在这些“看起来多余”的约束里。

2.2 建表与约束:DDL 里的血泪经验

建表语句谁都会写,但实验五级别的建表要求你考虑三件事:主键选型、外键级联策略、默认值与检查约束。下面这段是典型的学生选课核心表,注意注释里标出的易错位置。

CREATE TABLE student ( sno CHAR(10) PRIMARY KEY, -- 学号定长,别用 VARCHAR 导致索引膨胀 sname VARCHAR(20) NOT NULL, class_id CHAR(8) NOT NULL, gender CHAR(1) CHECK (gender IN ('M','F')), -- 检查约束别漏 FOREIGN KEY (class_id) REFERENCES class(class_id) ON UPDATE CASCADE ON DELETE RESTRICT -- 删除班级前必须先处理学生 ); CREATE TABLE enrollment ( sno CHAR(10), cno CHAR(8), score DECIMAL(5,1) CHECK (score BETWEEN 0 AND 100), term CHAR(6) NOT NULL, PRIMARY KEY (sno, cno, term), -- 联合主键必须含学期,否则重修冲突 FOREIGN KEY (sno) REFERENCES student(sno) ON DELETE CASCADE, FOREIGN KEY (cno) REFERENCES course(cno) ON DELETE RESTRICT );

参数说明:ON DELETE CASCADE用在选课表上是因为学生注销后选课记录应随之清理;ON DELETE RESTRICT用在课程上是因为课程被引用时不允许直接删,必须先确认没有在读记录。最容易忽略的是联合主键里的term——很多实验只写(sno, cno),结果同一学生重修同一门课就插不进去,或者插进去覆盖了旧成绩。建完表后一定用\d enrollment或SHOW CREATE TABLE回看一遍实际约束,别信自己手写的记忆。

2.3 查询与视图:把复杂逻辑收进一层

实验五的查询题通常不是单表过滤,而是“找出每门课平均分高于全体平均分的课程”这类嵌套。写这类 SQL 的稳定套路是先写子查询再套外层,别一上来就堆 JOIN。视图的作用在这里体现得很明显:把频繁复用的多表连接固化成视图,后续查询只面对一个逻辑表,既减少重复也降低出错面。

CREATE VIEW v_course_stat AS SELECT c.cno, c.cname, COUNT(e.sno) AS stu_cnt, AVG(e.score) AS avg_score FROM course c LEFT JOIN enrollment e ON c.cno = e.cno GROUP BY c.cno, c.cname; -- 查平均分高于全校平均的课程 SELECT * FROM v_course_stat WHERE avg_score > (SELECT AVG(score) FROM enrollment);

逻辑说明:视图里用LEFT JOIN是为了让没人选的课也出现在统计中,COUNT(e.sno)而不是COUNT(*)才能正确返回 0。外层子查询算全校平均分时只取score,自动忽略 NULL。这里常见的误用是把AVG写在外层导致分组混乱,或者视图里用了WHERE过滤掉空选课程,后面统计口径就对不上。

3. 事务、权限与完整性:实验五真正拉开差距的部分

3.1 事务边界:什么时候 BEGIN,什么时候 COMMIT

实验五如果涉及选课退课、成绩录入这类多步操作,就一定绕不开事务。事务不是“加个 BEGIN 显得专业”,而是为了保证一组写操作要么全成要么全败。典型场景:学生退课需要同时删除选课记录并给课程容量加一,这两步必须在一个事务里。

BEGIN; DELETE FROM enrollment WHERE sno = '2023001' AND cno = 'C001' AND term = '202401'; UPDATE course SET capacity = capacity + 1 WHERE cno = 'C001'; COMMIT;

参数与失败处理:执行前先确认隔离级别,实验环境默认读已提交即可;如果第二步更新影响行数为 0,说明课程号写错,此时应ROLLBACK而不是继续提交。最容易踩的坑是把COMMIT写在循环里,导致部分成功部分失败,数据处于半截状态。验证事务是否生效的办法是开两个会话,一个BEGIN后不提交,另一个查同一行,看是否被阻塞——这个黑匣子式的排查手段比反复读代码有效得多。

3.2 权限与角色:GRANT 不是走过场

实验五常要求“给某类用户只读权限”或“允许某角色更新成绩但不能删表”。这类题考的是最小权限原则。写法上先建角色再授权,最后把角色赋给用户,比直接对用户逐条 GRANT 更清晰,也更容易在复查时看出漏了哪条。

CREATE ROLE score_editor; GRANT SELECT ON student TO score_editor; GRANT UPDATE (score) ON enrollment TO score_editor; -- 列级授权,只能改成绩列 GRANT score_editor TO user_a;

注意UPDATE (score)是列级权限,只允许改成绩列,不能改选课学期或学号,这比整表 UPDATE 安全得多。常见错误是图省事写GRANT ALL ON enrollment TO user_a,实验判分时会被扣“权限过大”。复查时用\dp enrollment或查询系统权限表,确认实际生效的权限和你以为的一致。

3.3 完整性验证:写完脚本怎么自证没漏

脚本跑通不等于做对。实验五的完整性验证要覆盖三类:实体完整性(主键不重复)、参照完整性(外键不悬空)、用户定义完整性(CHECK 生效)。最直接的办法是故意插坏数据看数据库拦不拦。

-- 预期失败:学号重复 INSERT INTO student VALUES ('2023001','测试','C01','M'); -- 预期失败:班级不存在 INSERT INTO student VALUES ('2023999','测试','C99','M'); -- 预期失败:成绩越界 INSERT INTO enrollment VALUES ('2023001','C001',150,'202401');

三条都报错才说明约束真的建上了。如果某条静默成功,回去查建表语句是不是漏了对应约束。这一步花五分钟,能省掉后面调试查询时两小时的困惑。

4. 易错点清单:实验五最容易翻车的五个地方

易漏点一:联合主键漏掉业务维度。为什么漏:只盯着“学生+课程”唯一,忘了学期或批次也是区分维度。怎么补:建表前把“同一对组合能否出现多次”问一遍,能出现就说明主键还缺列。

易漏点二:外键级联策略一刀切。为什么漏:全写CASCADE图省事,结果删一门课把历史成绩全带走。怎么补:按业务语义逐条定,被引用的主数据用RESTRICT,从属明细才用CASCADE。

易漏点三:视图里过滤条件写死。为什么漏:调试时加了WHERE term='202401'忘了删,后续统计口径全偏。怎么补:视图只做连接和聚合,过滤留给外层查询;建完视图用SELECT * FROM v LIMIT 5抽查。

易漏点四:事务里混入 DDL。为什么漏:以为CREATE TABLE也能回滚,实际多数数据库 DDL 隐式提交。怎么补:DDL 单独执行,事务只包 DML;不确定时先查当前数据库对 DDL 事务的支持说明。

易漏点五:权限授给用户而非角色。为什么漏:直接GRANT给用户见效快,用户一多就失控。怎么补:统一走角色,用户只挂角色;复查时查角色成员关系而不是逐用户翻权限。

5. 考前复查清单:把实验五当一次自测跑完

复习到这一步,别再从头读脚本,按下面这张清单逐项打勾,哪项卡住就回对应章节补。清单的顺序就是实验五的执行顺序,跑一遍等于把整条链路自测一次。

检查项通过标准卡住回看
实体与关系每个需求都能指到一张表或一个约束2.1
建表约束主键、外键、CHECK 全部显式写出2.2
级联策略每条外键的删除行为有业务理由2.2 / 易漏点二
视图口径视图不含写死的过滤条件2.3 / 易漏点三
事务边界多步写操作成组出现,无循环 COMMIT3.1
权限最小化无GRANT ALL,敏感列用列级授权3.2
完整性自证三类坏数据插入均被拦截3.3

具体操作上,建议把清单转成一个可执行的验证脚本:先DROP再重建,按顺序插入正常数据,再逐条插坏数据确认报错,最后用两个会话验证事务阻塞。整个过程控制在十分钟内,比反复读代码可靠得多。我自己的习惯是每次交实验前强制走一遍“删库重建+坏数据注入”,有一次就是靠这一步发现外键写成了CASCADE,差点把课程主表删穿。从那以后我每次建完表都先跑三条坏数据,确认拦得住才继续往下写。希望这份梳理帮到你,把实验五当成一次完整的链路自测,而不是又一份要抄的脚本。

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