MySQL学生成绩管理系统:从ER图到存储过程的完整实验指南
简介面向数据库课程设计与期末成绩管理场景这份PDF实验报告围绕MySQL学生成绩管理系统的完整设计过程展开适合计算机专业学生撰写课程设计报告时参考同时也为数据库入门者展示了课程设计报告的常规写法。报告覆盖项目背景与目的、可行性分析、需求分析、性能要求与数据库设计等环节结合Eclipse、MySQL 5.6.17、Navicat等常用开发环境给出技术选型分析并详细梳理教师/学生两种身份的登录权限、班级管理、成绩批量录入与查询统计、学生信息批量导入等功能需求。压缩包仅含1个PDF文件总大小486KB便于统一阅读与存档目前已有10426人浏览/学习说明该资源在数据库设计类资料中具有较高参考认可度。数据库设计部分还提供了顶层数据流图、数据字典以及学生、教师、课程、班级、系等核心表结构说明可帮助读者理清从需求分析到库表落地的完整思路。整体来看资源内容既能辅助课程设计文档写作也能为后续成绩管理原型开发提供完整参考框架。1. MySQL学生成绩管理系统为什么这套实验报告最值得认真做期末前一周老师丢下一句话下周交 MySQL学生成绩管理系统设计实验报告。这件作业看起来简单真动手的人一半卡在表结构设计一半卡在 SQL 写出来却不知道怎么讲清楚。这套系统本质上是把“设计一个数据库”这件事走完一遍从实体关系建模、建库建表、插入数据到统计报表、存储过程、触发器、权限配置。它能解决的不只是交差而是把 MySQL 最常考的那批操作——排序、分组、连表、事务、索引——全部串成一条线。适合正在学数据库的本科生也适合面试前临时补 MySQL 实操的应届生。2. 实体与关系建模学生、课程、成绩三张表怎么设计才不返工2.1 为什么成绩必须单独拆成一张表多对多关系与三种异常很多第一次做实验报告的同学第一版表结构长这样学生表里放一个“课程1成绩、课程2成绩、课程3成绩”或者把所有成绩拼到一个字段里。这种设计最大的问题是学生和课程是多对多关系一个学生选多门课一门课有多个学生。把成绩塞进学生表意味着一个人选了五门课学生表里就要出现五行同一学号的数据。这五行数据带来的麻烦可以数出三个更新异常学生改手机号要同时改五行漏改一行就是数据不一致插入异常新生还没选课他的“课程成绩”字段全是空信息不完整删除异常删掉一门课的成绩连带把学生姓名、手机号也删掉了。这就是为什么非要符合第二范式非主属性必须完全依赖于主键不能只依赖主键的一部分。正确的做法就是把成绩抽成独立的 score 表学生和课程各留一张主表。下面这张表可以直观看到一张表方案和三张表方案的差别。设计方式数据冗余改学生信息加新课统计平均分单表平铺学号姓名重复 N 次需要更新 N 行要改表结构加字段要把多个成绩字段拼起来算学生表 课程表 成绩表无冗余只改 student 一行只往 course 加一行对 score 表聚合即可这个判断是整个实验报告的地基写需求分析章节时把这张对比表放进去比堆一页文字更有说服力。2.2 从 ER 图到关系模式最小可运行的三张表结构按规范化的思路最终关系模式落在三张表上。学生表主键是学号课程表主键是课程号成绩表用复合主键学号 课程号保证一个学生同一门课最多只有一条成绩记录。student(student_id, student_name, gender, birth_date, phone) course(course_id, course_name, credit, semester) score(student_id, course_id, score, exam_date)这里有一个在实验报告里经常被追问的选型问题成绩表到底用复合主键还是独立的自增主键我一般建议实验报告用复合主键因为能直接证明“一个学生选同一门课只允许一条成绩”这个业务规则老师一眼就看明白。工程上如果允许同一学期重复修课、补考多次可以改成自增主键再加唯一索引约束正常的那条记录。两种方案都不错关键是你的实验报告里前言和后语要一致别前面画 ER 图用的是复合主键建表时却写成了自增 ID。ER 图里还要画清楚联系的类型学生与课程之间是“选课”联系联系本身带成绩和考试日期两个属性所以它不是一个简单的连线而是一个菱形加属性。这个细节写进概念设计章节能避免“成绩字段到底属于哪个实体”的争论。2.3 成绩表设计里的三个“伪需求”想清楚再做伪需求一给成绩表加“排名”字段。课程排名是查询时算出来的结果属于派生数据存进表里每次成绩变动都要重算纯属给自己挖坑。伪需求二在学生表里加“平均分”字段。同样是派生数据违反第二范式成绩表一更新学生表就得跟着改事务边界被扯得很远。伪需求三用一张“补考表”记录所有补考还是用状态字段标记我的做法是在 score 表上加一个 status 字段0 正常、1 补考、2 重修历史补考记录另建一张补考流水表。报告里要体现“可追溯”但不要把追溯做成主流程的负担。提示设计阶段多花半小时实施阶段少改一晚上表结构。实验报告最怕的就是写完了回头发现 ER 图跟建表 SQL 对不上。3. 建库建表与数据导入DDL、索引和日期字段的三个坑3.1 完整建库建表 DDL字符集、引擎与外键策略的落地确定好关系模式接下来就是把设计转成能跑起来的 SQL。建库时字符集直接选 utf8mb4别再用 utf8utf8 在 MySQL 里是 utf8mb3存不了 emoji 和部分生僻字实验报告里的中文姓名、课程名倒是没影响但后面要导入的 Excel 数据里一旦出现特殊符号就是乱码这个坑我踩过两次。存储引擎选 InnoDB不要为了“查得快”选 MyISAM。成绩系统要演示事务、外键、行级锁这些都是实验报告的加分项MyISAM 全都不支持。外键策略上学生表改学号或删学生时成绩要跟随级联处理所以成绩表的 student_id 外键用 ON DELETE CASCADE ON UPDATE CASCADE课程表删课程要谨慎用 ON DELETE RESTRICT 防止误删还在被成绩引用的课程。CREATE DATABASE IF NOT EXISTS student_score_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE student_score_db; CREATE TABLE student ( student_id CHAR(10) NOT NULL COMMENT 学号如 2024010101, student_name VARCHAR(30) NOT NULL COMMENT 姓名, gender ENUM(男,女) DEFAULT 男 COMMENT 性别, birth_date DATE DEFAULT NULL COMMENT 出生日期, phone VARCHAR(20) DEFAULT NULL COMMENT 手机号, PRIMARY KEY (student_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生表; CREATE TABLE course ( course_id CHAR(6) NOT NULL COMMENT 课程号如 C001, course_name VARCHAR(50) NOT NULL COMMENT 课程名, credit DECIMAL(3,1) NOT NULL DEFAULT 0.0 COMMENT 学分如 3.5, semester VARCHAR(20) DEFAULT NULL COMMENT 开课学期如 2024-2025-1, PRIMARY KEY (course_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT课程表; CREATE TABLE score ( student_id CHAR(10) NOT NULL COMMENT 学号, course_id CHAR(6) NOT NULL COMMENT 课程号, score DECIMAL(5,1) DEFAULT NULL COMMENT 百分制成绩NULL 表示未录入, exam_date DATE DEFAULT NULL COMMENT 考试日期, PRIMARY KEY (student_id, course_id), KEY idx_course_id (course_id), CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student (student_id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course (course_id) ON DELETE RESTRICT ON UPDATE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT成绩表;讲一下几个“容易被忽略但报告里值得写”的点。学号和课程号用 CHAR 而不是 VARCHAR因为它们是定长编码查询等值比较时效率更高如果学校学号里有字母CHAR 也一样适用。score 用 DECIMAL(5,1) 而不是 INT体育、实验课成绩经常有 89.5 这种小数百分制下最大 100.05 位有效数字足够。DECIMAL 是精确类型不会出现 FLOAT 那种 0.1 加 0.2 不等于 0.3 的误差统计平均分时这很关键。注意score 表的 score 字段允许 NULL含义是“这门课还没录入成绩”不是 0 分。用 NULL 还是 0 会影响第 4 章平均分的计算结果后面详细说。3.2 造测试数据INSERT 批量写入、字符串转日期与默认值为 0 的陷阱实验报告需要一组能讲出故事的测试数据至少 3 个学生、3 门课、每个学生选 2 到 3 门课。太少看不出 JOIN 和 GROUP BY 的效果太多了又显得刻意。先插学生表和课程表再插成绩表顺序不能反外键约束会拦住你。INSERT INTO student (student_id, student_name, gender, birth_date, phone) VALUES (2024010101, 张三, 男, 2004-03-12, 13800000001), (2024010102, 李四, 女, 2004-07-25, 13800000002), (2024010103, 王五, 男, 2005-01-08, 13800000003); INSERT INTO course (course_id, course_name, credit, semester) VALUES (C001, 数据库原理, 3.5, 2024-2025-1), (C002, 数据结构, 4.0, 2024-2025-1), (C003, 操作系统, 3.0, 2024-2025-2); INSERT INTO score (student_id, course_id, score, exam_date) VALUES (2024010101, C001, 88.0, STR_TO_DATE(2024-11-10, %Y-%m-%d)), (2024010101, C002, 76.5, STR_TO_DATE(2024-12-20, %Y-%m-%d)), (2024010102, C001, 91.0, STR_TO_DATE(2024-11-10, %Y-%m-%d)), (2024010102, C003, NULL, STR_TO_DATE(2025-06-15, %Y-%m-%d)), (2024010103, C002, 58.0, STR_TO_DATE(2024-12-20, %Y-%m-%d));成绩表里我故意留了一条 NULL就是为了在第 4 章演示 AVG 对 NULL 和 0 的不同处理。为什么 INSERT 里要写 STR_TO_DATE 而不是直接写字符串MySQL 对 2024-11-10 这类字符串插 DATE 字段会做隐式转换多数情况能成功但你的 MySQL 服务端 sql_mode 如果开了严格模式非法日期会直接报错而不是自动转。更重要的场景是从 CSV 导入Excel 里日期格式五花八门2024/11/10、20241110、11-10-2024 都有用 STR_TO_DATE 可以统一指定格式解析这是“将字符串转为日期”最可靠的写法。有人喜欢给成绩字段加DEFAULT 0理由是没有成绩时默认显示 0。这个习惯在成绩系统里很危险0 分和缺考是两个业务含义缺考的学生不应该排在平均分里被拉低。数据录入阶段拿不准的建议直接保持 DEFAULT NULL报表输出时再用 COALESCE(score, 0) 处理显示层。3.3 索引怎么建成绩排序和连表查询的 EXPLAIN 实测实验报告里索引不需要多建多了反而占用空间、拖慢写入。最核心的两个查询是“按课程查成绩单并排序”和“查某学生的所有成绩”对应下面两条 SQL。EXPLAIN SELECT s.student_name, c.course_name, sc.score FROM score sc JOIN student s ON sc.student_id s.student_id JOIN course c ON sc.course_id c.course_id WHERE c.course_id C001 ORDER BY sc.score DESC;在没有辅助索引时EXPLAIN 的 type 列往往是 ALL表示全表扫描rows 显示要扫 5 行。数据量小感觉不出来但报告里可以对比说明索引前后的访问路径。给成绩表加上按课程和分数组织的复合索引CREATE INDEX idx_score_course_score ON score (course_id, score);建立之后再跑 EXPLAINtype 从 ALL 变成 refExtra 里可能出现 Using index conditionrows 明显减少。这个复合索引的字段顺序有讲究course_id 放在前面用于定位课程score 放在后面用于排序这样 ORDER BY sc.score DESC 可以走索引顺序避免 filesort。实验报告里把两次 EXPLAIN 的输出截图放一起是“物理设计”章节里最扎实的证据。提示索引不是越多越好。成绩表里已经有主键 (student_id, course_id)再加这一个复合索引就足够覆盖 90% 的实验查询需求。4. 核心查询与报表 SQL从单表分组到三表 JOIN 的完整实验路径4.1 成绩单查询三表 JOIN、排序与 LIMIT 分页的标准写法实验报告的核心演示从“查一张成绩单”开始。成绩单要展示学号、姓名、课程名、成绩这四列来自三张表必须用 JOIN 把关系重新拼起来。先过滤课程再排序最后分页这是最常见的执行顺序理解方式。SELECT s.student_id, s.student_name, c.course_name, sc.score FROM score sc JOIN student s ON sc.student_id s.student_id JOIN course c ON sc.course_id c.course_id WHERE c.course_id C001 ORDER BY sc.score DESC, s.student_id ASC LIMIT 0, 20;ORDER BY 里先按分数降序分数相同的再按学号升序保证排序结果是确定的分页翻页时不会出现同一行数据来回跳。LIMIT 0, 20 是 MySQL 的旧写法等价于 LIMIT 20 OFFSET 0实验报告里两种都可以写但要统一。这个查询在 MySQL 里是典型的“小表驱动大表”优化器会自己选驱动顺序不用手工改。4.2 汇总统计GROUP BY 平均分、及格率与每科前三名窗口函数如果实验报告只写查询那只能算及格能把统计写明白才有“管理”的味道。按课程统计平均分、最高分、最低分和及格率是最经典的一组 SQL也是 mysql 面试题里常翻牌子的考点。SELECT c.course_id, c.course_name, COUNT(*) AS total_stu, AVG(sc.score) AS avg_score, MAX(sc.score) AS max_score, MIN(sc.score) AS min_score, SUM(CASE WHEN sc.score 60 THEN 1 ELSE 0 END) / COUNT(*) AS pass_rate FROM score sc JOIN course c ON sc.course_id c.course_id GROUP BY sc.course_id, c.course_name ORDER BY avg_score DESC;这里有个必须讲清楚的坑GROUP BY sc.course_id 时SELECT 里出现了 c.course_nameMySQL 5.7 以上默认开 ONLY_FULL_GROUP_BY会直接报错。解决方法是把 c.course_name 也写进 GROUP BY或者用 ANY_VALUE(c.course_name)。在实验报告里解释这个报错本身就是体现你对 MySQL 机制理解的好素材。COUNT(*) 统计的是成绩记录数如果只想统计“有分数的人”要改成 COUNT(score)两者在有 NULL 时结果不一样。“每科前三名”这类需求以前要用变量或自连接实现MySQL 8.0 以后用窗口函数一行搞定这是实验报告里最能炫技又能讲清楚原理的部分。SELECT s.student_id, s.student_name, c.course_name, sc.score, RANK() OVER (PARTITION BY sc.course_id ORDER BY sc.score DESC) AS rank_no FROM score sc JOIN student s ON sc.student_id s.student_id JOIN course c ON sc.course_id c.course_id ORDER BY c.course_id, rank_no;PARTITION BY 对课程分组ORDER BY 在组内按分数降序RANK() 遇到同分会并列且跳过后续名次。如果希望同分不占名次用 DENSE_RANK()如果只要唯一的第 1 名用 ROW_NUMBER()。三者区别写进实验报告的“查询设计”章节比罗列十条语法更有价值。4.3 不及格名单与 UPDATE 补考标记事务里怎么改成绩统计出来之后业务动作是给不及格的学生打补考标记。首先要给成绩表加一个 status 字段用 ALTER TABLE 实现然后写一条 UPDATE把低于 60 分的记录标记为补考。ALTER TABLE score ADD COLUMN status TINYINT NOT NULL DEFAULT 0 COMMENT 0 正常1 补考2 重修; START TRANSACTION; UPDATE score SET status 1 WHERE score 60 AND status 0; -- 模拟检查先看看受影响的记录是不是预期的 SELECT s.student_name, c.course_name, sc.score, sc.status FROM score sc JOIN student s ON sc.student_id s.student_id JOIN course c ON sc.course_id c.course_id WHERE sc.status 1; COMMIT;事务的意义在于如果中途发现 UPDATE 影响行数不对可以 ROLLBACK 回滚而不是让错误数据直接落库。实验报告里建议保留一次主动 ROLLBACK 的演示说明你在处理数据时考虑过一致性。UPDATE 语句最容易翻车的点有两个一是忘了 WHERE 变成全表更新把正常成绩也标记成补考二是 WHERE 条件写错比如写成 score 60 AND status 0结果把已经补考过的记录又刷一遍触发第 5 章要讲的锁和日志问题。注意UPDATE 之前先跑一条等价的 SELECT 确认命中行数这是成本最低的后悔药。5. 实验报告必查项存储过程、触发器与权限配置的避坑排查5.1 存储过程DELIMITER、变量与错误处理一个都不能少存储过程是实验报告里的硬性加分项但也是翻车重灾区。最常见的报错是“SQL 语法错误”十有八九是 DELIMITER 没设置。mysql 命令行客户端默认用分号作为语句结束符存储过程内部也有分号如果不在创建前把分隔符临时换成 //MySQL 会在第一个内部语句结束时就认为 CREATE PROCEDURE 结束了。DELIMITER // CREATE PROCEDURE sp_course_avg(IN p_course_id CHAR(6), OUT p_avg DECIMAL(5,2)) BEGIN SELECT AVG(score) INTO p_avg FROM score WHERE course_id p_course_id; IF p_avg IS NULL THEN SET p_avg 0; END IF; END// DELIMITER ; CALL sp_course_avg(C001, avg); SELECT avg AS avg_score;这个存储过程接收课程号输出该课程平均分。SELECT ... INTO 把聚合结果赋给输出参数如果课程号不存在AVG 返回 NULL这里用 IF 把它兜底成 0省得调用方再判空。在 Navicat 里创建存储过程时图形界面会自动处理 DELIMITER但在 mysql 命令行、Workbench 和写脚本时必须手动写好这两行这是 mysql 声明存储过程最容易忽略的第一步。存储过程里的错误处理也有讲究。可以在 BEGIN 块里声明DECLARE EXIT HANDLER FOR SQLEXCEPTION捕获异常后做日志记录再退出。这个写进报告能体现你对“存储过程不只是 SQL 包装”的理解——它还能做流程控制。5.2 触发器成绩变更日志表与“慎用”的边界触发器是另一个报告常写、工程里常被劝退的功能。这里做一个最安全的场景记录成绩变更历史。先建一张日志表再创建 AFTER UPDATE 触发器。CREATE TABLE score_log ( log_id INT AUTO_INCREMENT PRIMARY KEY, student_id CHAR(10) NOT NULL, course_id CHAR(6) NOT NULL, old_score DECIMAL(5,1) DEFAULT NULL, new_score DECIMAL(5,1) DEFAULT NULL, op_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT成绩变更日志; CREATE TRIGGER trg_score_update AFTER UPDATE ON score FOR EACH ROW BEGIN INSERT INTO score_log (student_id, course_id, old_score, new_score) VALUES (OLD.student_id, OLD.course_id, OLD.score, NEW.score); END;OLD 和 NEW 是 MySQL 触发器里的特殊引用OLD 代表更新前的行NEW 代表更新后的行。成绩从 76.5 改成 80.0日志表就会多一条记录。实验报告里值得写清楚触发器的边界不能在触发器里再对同一张表做 UPDATE 或 INSERT否则会递归触发MySQL 直接报错也不能依赖触发器做复杂业务计算否则排查问题时你会想把设计它的自己找出来打一顿。这个触发器放在这里恰好和 4.3 的补考标记 UPDATE 联动——每次改成绩都会留下痕迹报告里可以展示这条链路。5.3 避坑排查ERROR 2002、锁表、GROUP BY 报错与连接认证这一节是给所有照着上面步骤做、却跑不出预期结果的人准备的排查清单。坑一ERROR 2002 (HY000): Cant connect to local MySQL server through socket现象在 mysql 命令行执行 mysql -uroot -p报错提示通过 socket 连接失败。原因分两类一是 MySQL 服务确实没启动二是服务启动了但 socket 文件路径和客户端默认路径不一致后者常见于手动编译安装或者机器上有多个 MySQL 实例。解决先跑 systemctl status mysql或 mysqld 对应的服务名服务没起来就启动路径不一致时用 SHOW VARIABLES LIKE socket 查实际路径再通过 mysql -u root -p -S /实际路径/mysql.sock 连接或者干脆走 TCP加 -h 127.0.0.1 -P 3306 绕开 socket 机制。坑二UPDATE 执行后一直转圈锁等待超时现象UPDATE score 语句执行后卡住报 Lock wait timeout exceeded。原因另一个会话先改了同一行数据但没 COMMIT事务持有行锁不释放或者有人执行了大事务行锁升级成了表锁。解决开一个新会话执行 SHOW PROCESSLIST看 State 列是否为 Waiting for table metadata lock找到阻塞源会话的 ID执行 KILL 该 ID。预防手段是事务短小、及时 COMMIT实验报告里演示 UPDATE 时不要开两个终端反复做交叉修改。坑三SELECT 报错 “which isnt in GROUP BY”现象执行含 GROUP BY 的统计语句报错提示某个列不在 GROUP BY 中。原因MySQL 5.7 开始默认启用 ONLY_FULL_GROUP_BY 模式。解决按第 4 章写法把查出的非聚合列补进 GROUP BY或者用 ANY_VALUE() 包住辅助列。不要图省事直接把 sql_mode 里的 ONLY_FULL_GROUP_BY 删掉那会让你在面试时被追问得很难看。坑四AVG 平均分和手算结果不一样现象统计出的平均分比自己拿计算器算的低了一截。原因成绩表里缺考记录用 0 填充了AVG 会把这 0 分算进分母。解决缺考保持 NULLAVG 会自动忽略 NULL如果业务必须显示 0用 COALESCE(score, 0) 在查询时转换而不是写库时填 0。坑五Navicat 连接 MySQL 8.0 报认证插件错误现象连接报 Authentication plugin caching_sha2_password cannot be loaded或者 Access denied。原因MySQL 8.0 默认认证插件是 caching_sha2_password老版本图形客户端不认识。解决升级 Navicat/Workbench 到支持 MySQL 8 的版本临时方案是 ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 密码但只建议在实验环境做生产库尽量保证客户端版本配套。做远程连接实验时还要检查 bind-address 配置是否允许外部访问默认绑 127.0.0.1 时远程 IP 是连不进来的。提示以上五条里坑二和坑四在教学环境出现频率最高。写报告时不一定要把每个坑都复现一遍但把排查过程和 SHOW PROCESSLIST 的截图放进去这份实验报告的成色立刻不一样。6. 交报告前的最后一步用 SHOW 和 EXPLAIN 做一次全覆盖自查6.1 对照实验报告章节做验收每章对应一条验证命令实验报告通常分需求分析、概念设计、逻辑设计、物理设计、数据库实施、运行维护六节。每一节都有一个对应的“自证命令”交之前花十分钟跑一遍。实验报告章节对应产物验证命令概念结构设计ER 图与 score 表主外键定义对照逻辑结构设计关系模式SHOW CREATE TABLE score物理结构设计引擎、字符集、索引SHOW INDEX FROM score数据库实施建表、插入、查询、统计第 3、4 章 SQL 全部重跑一遍运行维护备份与恢复mysqldump -u root -p student_score_db backup.sql最容易被忽视的是运行维护。实验报告的结尾通常要求“对数据库进行备份和恢复操作”一句 mysqldump 就能补上这个空缺同时把备份文件恢复到另一个库名验证备份可用。SHOW CREATE TABLE score; SHOW INDEX FROM score; EXPLAIN SELECT s.student_name, sc.score FROM score sc JOIN student s ON sc.student_id s.student_id WHERE sc.course_id C001; SELECT COUNT(*) FROM score;6.2 一个能救命的验收习惯用 source 跑完整脚本并留档我最后说一个血泪经验。当年交这类报告我在 Navicat 里逐条执行成功截图也存了结果老师要求用 source 命令整跑一遍 SQL 脚本一下就暴露出两个问题一是脚本里没有 USE student_score_db掉进了默认库二是插入中文数据时终端字符集没切到 utf8mb4屏幕上全是乱码。之后我做了一个固定动作把建库、建表、插入、查询、统计、存储过程、触发器按顺序写进一个 create_all.sql用 mysql 命令行执行source /路径/create_all.sql完整跑通再把输出重定向到一个文本文件留档。整跑能通过的脚本才是真的脚本逐条能过的不算。索引调优也别只建不验。每次加完索引都重新 EXPLAIN 一遍如果访问路径没有任何变化说明这个索引没被用上常见原因是 WHERE 条件里对索引列做了函数运算或者两个表关联字段的字符集不一致导致隐式转换。把这些自查结论写进报告的“调优过程”里比单纯贴出正确结果更有说服力。我自己做这套实验报告吃过两次亏一次是日期字段用字符串硬插导致数据错乱一次是触发器里想同时改 score 表结果 MySQL 直接报错。吃一堑长一智之后凡是涉及成绩的库我都固定留一份备份、保持 NULL 语义、所有脚本经 source 验证后再截图。这套 MySQL学生成绩管理系统做下来你得到的不是一份能交差的报告而是一套以后接真实报表需求也能直接套用的数据库基本功。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →