ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

北邮研一数据库大作业:学生成绩管理系统从建表到触发器完整实现

北邮研一数据库大作业:学生成绩管理系统从建表到触发器完整实现 简介这份资源是北邮研一数据库课程大作业的完整详解文档面向正在学习数据库系统、需要完成课程设计的高校学生。内容围绕学生成绩管理系统展开涵盖需求分析、数据库设计、ER图绘制、逻辑结构设计与建表程序等环节可帮助读者理清从需求到实现的完整设计思路。压缩包内共1个docx文件约503KB以文字与图表形式呈现设计过程与数据字典。文档详细给出Course、Student、Sc、Teacher四张表的字段定义、主键与外键约束并说明学生与课程的一对多关系及依赖表Sc的建立方式同时包含不及格学生名单统计、无教学任务教师查询等功能设计。目前已有606人学习下载适合需要参考课程设计框架、对照表结构设计与SQL建表语句的读者使用。1. 北邮研一数据库大作业拆解学生成绩管理系统从建表到触发器怎么落地如果你正在搜“北邮研一数据库大作业”大概率不是想听数据库概论而是手里有一个必须交的学生成绩管理系统想知道四张表怎么设计、SQL 怎么写、Navicat 怎么配合、哪些地方容易翻车。这份资源就是围绕这个题目做的完整实现Course、Student、Sc、Teacher 四张表覆盖成绩录入、成绩查询、不及格统计、无教学任务教师查询还带视图、存储过程、触发器、复杂查询和运行环境说明。它适合两类人一类是刚上手 MySQL、需要照着把作业跑通的研一同学另一类是想快速判断这份设计能不能直接复用到课程设计里的开发者。下面按“先能建起来、再能查出来、最后能扛住答辩追问”的顺序拆。2. 四张表怎么建从 ER 图到 MySQL 建表语句的完整落地2.1 为什么是 Course、Student、Sc、Teacher 这四张表这个题目的核心关系不复杂一个学生可以选多门课一门课可以被多个学生选所以 Student 和 Course 之间是多对多。多对多在关系数据库里不能直接落成两张表必须抽一张联系表也就是 Sc。Sc 里放 sno、cno、degreesno 和 cno 做组合主键同时各自作为外键指回 Student 和 Course。Teacher 和 Course 的关系是“一位教师可以讲多门课一门课通常由一位教师负责”所以 Course 表里放 tno 作为任课教师编号这样“没有教学任务的老师”就能通过 Teacher 左连接 Course 后筛空值查出来。这里有个容易被忽略的点题目正文里 Course 表的“选课人数”字段写的是 tno这其实是笔误tno 是教师编号不是人数。真正建表时应该按逻辑结构设计里的 course 表来cno、cname、tno。如果你照着需求分析那一段把 tno 当人数用后面查“没有教学任务的老师”时字段含义会直接乱掉。我一般会先以逻辑结构设计为准再回头检查需求分析里的字段描述是否一致。2.2 建库建表的可执行 SQL下面这段可以直接在 MySQL 客户端或 Navicat 查询窗口里跑。注意库名用 test 是原文的写法实际交作业时建议改成 student_score 这类更语义化的名字避免和别的库混在一起。-- 创建数据库字符集用 utf8mb4 防止中文乱码 CREATE DATABASE test DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE test; -- 课程表cno 主键tno 是任课教师编号 CREATE TABLE course ( cno CHAR(5) NOT NULL, cname VARCHAR(20) NOT NULL, tno CHAR(3) NOT NULL, CONSTRAINT C1 PRIMARY KEY (cno) ); -- 学生表sno 主键其余字段允许为空 CREATE TABLE student ( sno CHAR(9) PRIMARY KEY, sname CHAR(8), ssex CHAR(2), smajor CHAR(20), sclass CHAR(10) ); -- 成绩表sno cno 组合主键degree 限制 0 到 100 CREATE TABLE sc ( sno CHAR(10) NOT NULL, degree DECIMAL(4,1), cno CHAR(5) NOT NULL, CONSTRAINT A1 PRIMARY KEY (sno, cno), CONSTRAINT A2 CHECK (degree 0 AND degree 100) ); -- 教师表tno 主键 CREATE TABLE teacher ( tno CHAR(3) NOT NULL, tname VARCHAR(8), tsex CHAR(2), tdept CHAR(16), CONSTRAINT C2 PRIMARY KEY (tno) );逻辑说明建表顺序建议先 course、student、teacher再 sc因为 sc 引用了前几张表的主键。参数上sno 在 student 里是 CHAR(9)在 sc 里是 CHAR(10)原文两处长度不一致实际插入时如果学号固定 9 位建议统一成 CHAR(9)否则会出现“同一个人在两个表里长度不同”的别扭情况。degree 用 DECIMAL(4,1) 能存 100.0CHECK 约束在 MySQL 8.0 之后才真正生效5.5 版本会解析但可能不强制这点答辩时如果被问到要能说清楚。2.3 插入测试数据时怎么避免外键悬空原文里插入语句用了中文引号直接跑会报语法错误必须换成英文单引号。另外原文 teacher 表的插入示例里字段个数和值个数对不上VALUES 里多了一个“计算机 1403”而 teacher 表只有 tno、tname、tsex、tdept 四列。这种地方就是典型的“复制粘贴翻车点”。-- 课程数据 INSERT INTO course VALUES (C01, 科学导论, 101); INSERT INTO course VALUES (C02, 高等数学, 102); INSERT INTO course VALUES (C03, 数据结构, 101); -- 学生数据 INSERT INTO student VALUES (120210332, 吴迪, 男, 计算机科学与技术, 4412); INSERT INTO student VALUES (120210455, 小明, 男, 计算机科学与技术, 4412); -- 教师数据注意列数要和值数一致 INSERT INTO teacher VALUES (101, 叶何斌, 男, 计算机学院); INSERT INTO teacher VALUES (102, 张老师, 女, 数学学院); INSERT INTO teacher VALUES (103, 李老师, 男, 计算机学院); -- 成绩数据 INSERT INTO sc VALUES (120210332, 86.0, C01); INSERT INTO sc VALUES (120210332, 55.0, C03); INSERT INTO sc VALUES (120210455, 72.5, C02);逻辑说明先插 course、student、teacher再插 sc是因为 sc 的 sno 和 cno 分别指向 student 和 course。如果顺序反了在开启外键约束的库上会直接失败。参数上degree 写 86.0 而不是 86能避免隐式类型转换带来的精度问题。测试数据里特意留了一个不及格成绩 55.0后面统计不及格名单时可以直接验证结果。3. 视图、存储过程和触发器把作业从“能跑”拉到“能答辩”3.1 视图 v_student 和 view_sc 的创建与修改视图在这个作业里承担两个作用一是把多表连接封装成简单查询二是演示“通过视图向基表插入数据”。原文里 v_student 查的是选修“科学导论”的学生学号、姓名和成绩这个视图适合放在答辩演示里因为它同时用到了 student、course、sc 三张表。-- 创建视图查询选修科学导论的学生成绩 CREATE VIEW v_student AS SELECT A.sno, A.sname, C.degree FROM student A JOIN sc C ON A.sno C.sno JOIN course B ON B.cno C.cno WHERE B.cname 科学导论; -- 查询视图 SELECT * FROM v_student; -- 创建可更新视图 view_sc CREATE VIEW view_sc AS SELECT sno, degree, cno FROM sc; -- 通过视图插入数据 INSERT INTO view_sc VALUES (120210455, 88.0, C01); -- 修改视图定义 ALTER VIEW view_sc AS SELECT sno, degree, cno FROM sc WHERE degree IS NOT NULL; -- 删除视图 DROP VIEW view_sc;逻辑说明v_student 用了 JOIN 而不是逗号连接可读性更好也不容易漏掉连接条件。view_sc 之所以能插入是因为它只来自单表 sc且没有聚合、去重、分组属于可更新视图。如果视图里带了 AVG、GROUP BY 或者 UNION插入就会失败。参数上ALTER VIEW 改的是视图定义不是数据DROP VIEW 只删视图不影响 sc 基表里的数据这两个点答辩时经常被追问。3.2 存储过程 proc_stud 和 num_sc 的参数设计存储过程是这份作业里比较能体现“数据库编程”的部分。原文给了两个一个按班级查学生一个统计某个学生的选课门数。第二个用了 IN 和 OUT 参数是典型的“输入学号、输出数量”模式。DELIMITER // -- 查询班级包含 4412 的学生 CREATE PROCEDURE proc_stud() READS SQL DATA BEGIN SELECT sno, sname, smajor FROM student WHERE sclass LIKE %4412% ORDER BY sno; END // -- 统计指定学号的课程成绩个数 CREATE PROCEDURE num_sc(IN tmp_sno CHAR(9), OUT count_num INT) READS SQL DATA BEGIN SELECT COUNT(*) INTO count_num FROM sc WHERE sno tmp_sno; END // DELIMITER ; -- 调用无参存储过程 CALL proc_stud(); -- 调用带 OUT 参数的存储过程 CALL num_sc(120210332, cnt); SELECT cnt;逻辑说明DELIMITER // 是为了让 MySQL 把存储过程内部的封号当成普通语句分隔符最后再恢复成封号。参数上IN 表示传入OUT 表示传出调用时用用户变量 cnt 接收。READS SQL DATA 表示过程只读数据不改数据这个声明在权限管理和答辩时都能加分。注意 tmp_sno 的长度最好和 student.sno 保持一致原文写 CHAR(9)但 sc.sno 是 CHAR(10)如果学号实际是 9 位建议统一。3.3 触发器 trig_student 和 delstudent 备份表触发器的需求是删除 student 里的学生时把学号和姓名写进 delstudent 表。这个设计本质上是一个简易审计日志答辩时可以说成“保留删除痕迹便于追溯”。-- 创建空备份表结构来自 student CREATE TABLE delstudent AS SELECT sno, sname FROM student WHERE 1 0; -- 创建删除触发器 CREATE TRIGGER trig_student AFTER DELETE ON student FOR EACH ROW INSERT INTO delstudent(sno, sname) VALUES (OLD.sno, OLD.sname); -- 验证删除一个学生 DELETE FROM student WHERE sname 李甜甜; -- 查看备份表 SELECT * FROM delstudent;逻辑说明CREATE TABLE ... AS SELECT ... WHERE 10 是常见的“只复制结构不复制数据”写法。触发器用 AFTER DELETE因为只有删除成功后才需要记录。OLD.sno 和 OLD.sname 代表被删除行原来的值MySQL 里删除操作只能用 OLD不能用 NEW。参数上FOR EACH ROW 表示行级触发器删一行触发一次。如果一次删多行delstudent 里会插入多条记录。4. 高频查询 SQL不及格名单、无教学任务教师和平均分怎么一次写对4.1 统计不及格学生名单的多表连接写法教务处要查各科不及格学生名单这个查询要同时拿到学生信息、课程信息和成绩。原文用的是 INNER JOIN这是对的因为不及格记录一定同时存在于 sc 和 student 中。-- 查询 C03 课程不及格的学生信息 SELECT A.sno, A.sname, A.ssex, A.smajor, A.sclass, B.degree FROM student A INNER JOIN sc B ON A.sno B.sno INNER JOIN course C ON B.cno C.cno WHERE C.cno C03 AND B.degree 60;逻辑说明连接顺序是 student 到 sc 到 course先通过 sno 关联学生和成绩再通过 cno 关联课程。WHERE 里同时限制课程号和分数能精确到“某一门课的不及格名单”。参数上degree 60 是不及格线如果学校有 60 分以下和 60 分整的区别边界要确认清楚。如果要把所有课程的不及格名单都列出来去掉 C.cno C03 即可但建议加上 ORDER BY C.cno, A.sno方便阅读。4.2 查询没有教学任务的老师名单这个需求是整份作业里最容易写错的。核心思路是从 teacher 表出发左连接 course 表然后筛出 course 侧为 NULL 的记录。因为如果一位老师没有课左连接后 course 的字段全是 NULL。-- 查询没有教学任务的教师 SELECT T.tno, T.tname, T.tdept FROM teacher T LEFT JOIN course C ON T.tno C.tno WHERE C.cno IS NULL;逻辑说明LEFT JOIN 保证 teacher 表所有行都保留course 表匹配不上的行在 C.cno 上显示 NULL。WHERE C.cno IS NULL 就是筛出这些没匹配上的老师。参数上判断 NULL 必须用 IS NULL不能用 NULL这是 SQL 里最常见的坑之一。如果 course 表里 tno 允许为空还要考虑“课程存在但没分配老师”的情况那种场景下应该用 NOT EXISTS 或 NOT IN但本题的 course.tno 是 NOT NULL所以左连接方案足够。4.3 平均成绩和条件查询的边界计算某门课平均分、查选修某课的学生、插入新学生这些都属于基础操作但有几个边界要注意。-- 计算 C01 课程平均成绩 SELECT AVG(degree) AS avg_degree FROM sc WHERE cno C01; -- 查询选修高等数学的学生学号和姓名 SELECT A.sno, A.sname FROM student A INNER JOIN sc B ON A.sno B.sno INNER JOIN course C ON B.cno C.cno WHERE C.cname 高等数学; -- 插入新学生只填必填字段 INSERT INTO student (sno, sname, ssex) VALUES (120210455, 小明, 男);逻辑说明AVG 会自动忽略 NULL如果某学生 degree 为空不会拉低平均分但也不会被计入。参数上插入语句只写部分列时其余列取默认值或 NULL前提是这些列允许为空。如果 sno 已经存在会报主键冲突这是正常的说明约束在起作用。5. 避坑与排查这份大作业最容易翻车的五个地方5.1 中文引号导致 SQL 语法错误现象把原文里的 INSERT 语句复制到 Navicat 里执行报 “You have an error in your SQL syntax”。原因原文用的是中文全角引号 ‘ ’ 和 “ ”MySQL 只认英文半角单引号。解决把所有值两边的引号替换成英文单引号建表语句里的注释 // 也要改成 -- 或 /* */否则同样会报错。5.2 字段长度不一致导致关联查不出数据现象student.sno 是 CHAR(9)sc.sno 是 CHAR(10)插入时看起来都有值但 JOIN 之后查不到记录。原因CHAR 类型在比较时会补空格长度不一致时可能影响等值匹配尤其是数据里混有前后空格。解决统一 sno 长度为 CHAR(9)插入前用 TRIM() 清理空格或者建表时就按同一标准定义。5.3 CHECK 约束在 MySQL 5.5 不生效现象degree 插入 -10 或 200表里居然存进去了。原因MySQL 5.5 及更早版本会解析 CHECK 但不会强制执行只有 8.0.16 之后才真正生效。解决如果环境是 5.5成绩范围要在应用层或触发器里校验如果可以用 8.0保留 CHECK 并说明版本要求。答辩时被问到“你的约束真的生效了吗”要能答出这个版本差异。5.4 触发器删除后备份表没数据现象执行 DELETE 后delstudent 表是空的。原因可能是触发器创建失败但没注意报错或者删除条件没匹配到任何行也可能是 AFTER DELETE 写成了 BEFORE DELETE 但逻辑不对。解决先 SHOW TRIGGERS; 确认触发器存在再用 SELECT * FROM student WHERE sname李甜甜; 确认有数据最后检查 OLD.sno 和 OLD.sname 是否写对。5.5 Navicat 图形化操作和命令行结果不一致现象在 Navicat 里手动改了一条数据命令行查询结果和预期不同。原因Navicat 可能没有自动提交事务或者改的是视图而不是基表。解决在 Navicat 里确认当前连接的是 test 库修改后点“提交”命令行里用 SELECT * FROM sc; 直接验证基表。涉及视图更新时先确认视图是否可更新。6. 进阶技巧用 EXPLAIN 和索引把查询从“能跑”调到“能看”这份作业的查询数据量不大但答辩时老师很可能问一句“如果数据量大了怎么办”。这时候不要空谈优化直接上 EXPLAIN 看执行计划再决定加不加索引。我一般会先对 sc 表的 sno 和 cno 分别建索引因为这两个字段在连接和条件过滤里出现频率最高。-- 查看不及格查询的执行计划 EXPLAIN SELECT A.sno, A.sname, B.degree FROM student A INNER JOIN sc B ON A.sno B.sno WHERE B.degree 60; -- 在 sc 表上建索引 CREATE INDEX idx_sc_sno ON sc(sno); CREATE INDEX idx_sc_cno ON sc(cno); CREATE INDEX idx_sc_degree ON sc(degree); -- 再次查看执行计划对比 type 和 rows EXPLAIN SELECT A.sno, A.sname, B.degree FROM student A INNER JOIN sc B ON A.sno B.sno WHERE B.degree 60;逻辑说明EXPLAIN 输出里重点看 type、key 和 rows。type 从 ALL 变成 ref 或 range说明索引生效rows 变小说明扫描行数减少。参数上索引不是越多越好sc 表本身是组合主键 (sno, cno)已经能覆盖按 sno 或 snocno 的查询单独再建 idx_sc_sno 可能冗余但按 cno 单独查时 idx_sc_cno 有用。degree 上的索引在低选择性列上效果有限如果不及格人数占比很高优化器可能仍然走全表扫描这是正常的。还有一个容易被忽略的点存储过程和触发器在答辩演示时最好准备“失败案例”。比如故意插入一个重复学号展示主键冲突故意删除一个不存在的学生展示触发器不触发。这样比只演示成功路径更有说服力。我每次交这类作业前都会把建表、插数据、视图、存储过程、触发器、复杂查询按顺序完整跑一遍把报错信息也截图留着因为那些报错往往就是答辩时被追问的地方。从那以后我每次做数据库作业都强制走一遍“删库重建”流程确保脚本从头到尾可复现。希望帮到你。本文还有配套的精品资源点击获取
返回列表