ARTICLE DETAIL

资讯详情

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

MySQL期末大作业指南:图书借阅系统表设计、SQL与答辩避坑

MySQL期末大作业指南:图书借阅系统表设计、SQL与答辩避坑 简介这是一份《数据库应用》课程期末大作业的企业人事管理系统设计报告适合需要完成数据库课程设计或期末项目的同学参考。资源包含1个doc格式完整文档压缩包大小2.58MB已有6645人下载学习。报告从企业人事管理需求出发完整展示数据库设计的全过程先明确员工信息、考勤、薪资等信息与处理需求再完成概念结构设计中的员工、考勤、薪资、用户等实体划分然后给出Staff、Attendance、Salary、Puser四张核心表的逻辑与物理结构设计包含字段类型、主键、唯一性约束等细节。报告还涉及视图设计、数据安全保护如防止直接操作数据库、密码加密、角色权限以及系统实现思路。整体内容结构清晰可作为数据库建模实训、课程设计说明书或期末答辩汇报的参考样板尤其适合MySQL初学者对照梳理课堂所学理解从需求分析到物理建表再到安全设计的关键步骤。1. 数据库MySQL《数据库应用》期末大作业把“会查会插”做成“能答辩”的小系统很多同学做 MySQL《数据库应用》期末大作业最难受的不是 SQL 写不出来而是表结构一开始没想清做完功能才发现外键对不上、统计查不到只能删了重建。所谓“期末大作业”通常就是老师让你独立实现一个小型数据库应用把建库建表、增删改查、视图、存储过程、事务这些课上考点全部串进去。下面这条路线可以照着走选题和建表怎么做、测试数据怎么造、程序怎么连、哪些坑必须绕开以及答辩前怎么验证。适合正要交课程设计的学生也适合想快速复习 MySQL 核心操作的从业者。2. 选题与表结构设计从《图书借阅管理系统》看数据库课程设计的完整闭环2.1 为什么期末大作业首选“图书借阅管理”这类经典题我经手和看过的数据库课程设计题目不少像《学生选课系统》《超市收银系统》《员工考勤》《图书借阅管理系统》是出现频率最高的几类。图书借阅这个题几乎每个老师都备了现成要求原因不是旧而是它能覆盖《数据库应用》课的大纲实体关系、主外键、多对多、联合查询、统计报表、事务回滚。借一本书要同时改借阅记录和库存这就是天然的事务演示场景。你做这个系统答辩时老师问“为什么要有两张表”你能答得清楚换一个花哨的题目很容易把自己绕进“订单套订单”的递归里。选型的另一个理由是数据边界清楚。读者、图书、借阅记录三张表就能把业务闭环不存在复杂父子层级。对你来说期末大作业最怕的不是功能少而是做着做着发现自己驾驭不了。功能少点没关系但业务必须闭环能录入、能查询、能改状态、能删除、能统计。图书借阅正好四样全占。我一般会再给系统加一个“管理员/普通读者”的身份字段但只在应用界面区分不在数据库设计一张权限表。为什么权限表会引入“角色-用户-菜单”一堆关联ER 图复杂期末答辩时反而容易暴露弱点。三张核心表做扎实比堆十张关联表更划算。数据库设计这门课考的核心是“关系建模”不是“表越多越高级”。2.2 三张核心表的字段设计与建表 SQL建库前先把实体关系理清读者表 reader存储读者基本信息主键 idreader_no 唯一。图书表 book存储图书信息主键 idtotal 馆藏数量available 可借数量。借阅记录表 borrow一条记录对应一次借书含借书时间、应还时间、实际归还时间。一个读者可以借多本书一本书可以被多个人借过所以 borrow 表同时引用另外两张表的主键这就是多对多关系在关系型数据库里的标准解法。很多新手把借阅信息塞进 reader 表里统计“谁还没还书”要写三层子查询边写边难受。正确的做法是独立的 borrow 表三张表各司其职。下面是可以直接复制到 MySQL 8.0 执行的建表脚本CREATE DATABASE IF NOT EXISTS library_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE library_db; CREATE TABLE IF NOT EXISTS reader ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, reader_no VARCHAR(20) NOT NULL UNIQUE COMMENT 学号/工号登录用, reader_name VARCHAR(30) NOT NULL, phone VARCHAR(11) DEFAULT COMMENT 手机号允许空, status TINYINT NOT NULL DEFAULT 1 COMMENT 1正常 0停用, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE IF NOT EXISTS book ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, book_no VARCHAR(20) NOT NULL UNIQUE COMMENT 图书编号, title VARCHAR(100) NOT NULL COMMENT 书名, category VARCHAR(30) DEFAULT 未分类, total SMALLINT UNSIGNED NOT NULL DEFAULT 1 COMMENT 馆藏总数, available SMALLINT UNSIGNED NOT NULL DEFAULT 1 COMMENT 当前可借数, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;借阅表要特别注意还书时给 return_time 写入实际时间还没还的记录 return_time 为 NULL。这样比用 0 和 1 两个状态字段表达更自然后面统计逾期时写WHERE return_time IS NULL AND due_time NOW()就完事。CREATE TABLE IF NOT EXISTS borrow ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, reader_id INT UNSIGNED NOT NULL, book_id INT UNSIGNED NOT NULL, borrow_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, due_time DATETIME NOT NULL COMMENT 应还时间借书时borrow_time30天, return_time DATETIME NULL COMMENT 实际归还时间未还为NULL, CONSTRAINT fk_borrow_reader FOREIGN KEY (reader_id) REFERENCES reader(id), CONSTRAINT fk_borrow_book FOREIGN KEY (book_id) REFERENCES book(id), INDEX idx_borrow_status (reader_id, return_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;用一张对照表把三张表的分工理清楚表名核心字段在业务中的作用readerid、reader_no、reader_name、status读者档案登录账号来源bookid、book_no、title、total、available图书档案库存控制borrowreader_id、book_id、due_time、return_time借还事件连接读者和图书上面的 ENGINE 统一用 InnoDB原因是课程要求演示事务而 MyISAM 不支持行级锁和事务回滚外键也依赖 InnoDB。字符集单独指定为 utf8mb4别只写 utf8MySQL 里 utf8 实际是 utf8mb3存 emoji 或生僻字会报错。COLLATE 用 utf8mb4_general_cici 表示大小写不敏感图书编号查询时不至于因为大小写差一个字母查不到。VARCHAR(20) 后面跟的是字符数不是字节数学号工号足够。phone 用 VARCHAR(11) 而不是 INT因为手机号前导零会被 INT 丢掉。SMALLINT UNSIGNED 上限 65535馆藏数量完全够。status TINYINT 的容错比 char 好后面扩展状态时不用改表结构。建表时多花十分钟核对比数据填好后再 ALTER TABLE 舒服得多。2.3 MySQL 8.0 的默认值、sql_mode 与字符集三个选型细节建表时的“默认值”看起来简单但你在 MySQL 8.0 上会撞到两个有名的坑。第一个是 DATETIME 类型直接写DEFAULT 0000-00-00 00:00:00MySQL 8.0 默认开启 NO_ZERO_IN_DATE 和 NO_ZERO_DATE会直接报错。正确写法是DEFAULT CURRENT_TIMESTAMP或者写一个具体合法时间。第二个是“设置默认值为 0”的需求你写status TINYINT DEFAULT 0导数据时还是被插入 NULL原因是字段没有 NOT NULL程序又显式传了 NULL。正确做法是NOT NULL DEFAULT 0语义明确SUM 统计时也不会被 NULL 污染。再说 sql_mode。MySQL 8.0 默认启用 ONLY_FULL_GROUP_BY很多网上的老代码SELECT reader_name, COUNT(*) FROM borrow GROUP BY reader_id会执行失败因为 reader_name 没有出现在 GROUP BY 里。期末大作业的统计 SQL 最容易踩这个点。建议你写每一条统计语句时先在 MySQL Workbench 或命令行里跑通再粘进 Java/Python 代码里调试能省一半排查时间。最后是字符集。库、表、连接串三层都要一致。有些云数据库或本地旧配置默认 latin1只建表不指定字符集就会出现中文乱码。连接层要在 JDBC 连接串上加characterEncodingutf8这是 Java 驱动写法实际映射到 utf8mb4第 4 章会展开。到此表结构已经比多数同学只交一张“大宽表”的作业专业一个层次。3. 用命令行和 SQL 脚本把库跑起来建库建表、造测试数据与增删改查3.1 从 MySQL 安装到进入命令行的最小流程不管你是 Windows 还是 Linux做这个大作业我只推荐两个入口MySQL 官方的 MySQL Workbench 和命令行客户端 mysql。去 mysql 下载官网时选 MySQL Community Server 和 MySQL Workbench 两个安装包尽量别用第三方整合包能少很多 PATH 和版本冲突问题。网上的 mysql 安装教程很多核心就三步安装、设置 root 密码、把 bin 目录加进 PATH。MySQL 安装配置教程里最容易漏的就是服务没启动装完直接连当然失败。确认安装成功的命令mysql --version mysql -u root -p输入密码后进入交互终端SHOW DATABASES;能列出当前实例的数据库。mysql、information_schema、performance_schema、sys 是系统库不要动。你新建的业务库会和它们并排出现。命令行里每条 SQL 必须以分号结束否则按回车只会继续等下一行这是新手第一次碰 mysql 客户端最容易愣住的地方。3.2 用存储过程批量生成测试数据表建好了需要有足够的数据支撑模糊查询、分页和统计。手动一条条 INSERT 不现实。我用存储过程生成 200 个读者、500 本书、800 条借阅记录。存储过程本来就是课程得分点一举两得。USE library_db; DROP PROCEDURE IF EXISTS seed_reader; DELIMITER $$ CREATE PROCEDURE seed_reader(IN num INT) BEGIN DECLARE i INT DEFAULT 1; WHILE i num DO INSERT INTO reader(reader_no, reader_name, phone) VALUES ( CONCAT(R, LPAD(i, 4, 0)), CONCAT(读者, i), CONCAT(13, LPAD(FLOOR(RAND()*900000000), 9, 0)) ); SET i i 1; END WHILE; END$$ DELIMITER ; CALL seed_reader(200);先说 DELIMITER 的关键作用它把语句结束符临时改成 $$因为存储过程内部有分号不这样改mysql 客户端会在第一个分号处就把 CREATE PROCEDURE 截断直接报语法错误。LPAD 和 CONCAT 把数字补成 4 位让 reader_no 长得整齐。RAND() 生成随机手机号至少以 13 开头看起来真实。图书类别建议交错分布MySQL 存储过程里没有数组用 ELT 配合 RAND 选DROP PROCEDURE IF EXISTS seed_book; DELIMITER $$ CREATE PROCEDURE seed_book(IN num INT) BEGIN DECLARE i INT DEFAULT 1; WHILE i num DO INSERT INTO book(book_no, title, category, total, available) VALUES ( CONCAT(B, LPAD(i, 5, 0)), CONCAT(书名, i), ELT(1 FLOOR(RAND()*6), 计算机, 文学, 历史, 数学, 外语, 其他), 5, 5 ); SET i i 1; END WHILE; END$$ DELIMITER ; CALL seed_book(500);total 和 available 先都给 5后面生成借阅记录时再减少。注意存储过程造数时如果中途插入失败过程不会自动回滚所以先在测试库上跑通再完整执行。大作业提交前把造数脚本保存成 .sql 文件老师要恢复数据时直接source 文件名.sql就行。借阅记录的随机关联要注意业务一致性每借出一本未归还的书book.available 应该减一。为了避免同一本书被随机选中太多次把库存减成负数我加了一个可借数判断并保留最后一条 UPDATE 修正库存DROP PROCEDURE IF EXISTS seed_borrow; DELIMITER $$ CREATE PROCEDURE seed_borrow(IN num INT) BEGIN DECLARE i INT DEFAULT 1; DECLARE rd INT; DECLARE bk INT; DECLARE cnt INT DEFAULT 0; WHILE i num DO SET rd 1 FLOOR(RAND()*200); SET bk 1 FLOOR(RAND()*500); SELECT available INTO cnt FROM book WHERE id bk; IF cnt 0 THEN INSERT INTO borrow(reader_id, book_id, due_time, return_time) VALUES (rd, bk, DATE_ADD(NOW(), INTERVAL 30 DAY), IF(i % 4 0, NOW(), NULL)); IF i % 4 0 THEN UPDATE book SET available available - 1 WHERE id bk; END IF; END IF; SET i i 1; END WHILE; END$$ DELIMITER ; CALL seed_borrow(800); UPDATE book b SET available total - ( SELECT COUNT(*) FROM borrow br WHERE br.book_id b.id AND br.return_time IS NULL );后面这条 UPDATE 会把随机造数产生的库存偏差统一修正保证 book.available 与 borrow 表中“未还数量”严格对应。你在答辩前执行一次老师当场随机核对也不会穿帮。3.3 必考的增删改查INSERT、UPDATE、DELETE、SELECT 的边界期末大作业除了表和存储过程最直接的考点就是增删改查四个语句以及它们容易出错的条件。INSERT 最常见的问题是字段和值数量不匹配。我习惯显式写出字段清单不要用省略字段的 INSERT一旦表结构顺序调整数据就会串列INSERT INTO reader(reader_no, reader_name, phone, status) VALUES (R2024001, 张三, 13800000000, 1); INSERT INTO borrow(reader_id, book_id, borrow_time, due_time, return_time) VALUES (1, 1, NOW(), DATE_ADD(NOW(), INTERVAL 30 DAY), NULL);UPDATE 最容易出问题的是多表更新。还书场景需要两步把 borrow.return_time 改成当前时间再把 book.available 加一。这两条必须放在同一个事务里顺序是先还书记录后加库存UPDATE borrow SET return_time NOW() WHERE reader_id 1 AND book_id 1 AND return_time IS NULL; UPDATE book SET available available 1 WHERE id 1;如果顺序反过来第二步失败时库存已经被加了一次数据就不一致。事务用法我会在第 4 章用 JDBC 完整演示一句。DELETE 在图形化工具里常被 Safe Updates 挡住报 1175 错误。原因是工具默认开启防止误删要求必须带 KEY 条件。所以写成DELETE FROM borrow WHERE id 10;就好。不要在工具里图省事SET SQL_SAFE_UPDATES 0一旦条件写错就是全表删除那种血泪经验一次就够了。SELECT 是大作业里占比最大的部分。模糊查询注意 LIKE 通配符排序注意 ORDER BY 多写一列保证稳定SELECT reader_no, reader_name, phone FROM reader WHERE reader_name LIKE %张% ORDER BY reader_no DESC LIMIT 10 OFFSET 0;OFFSET 是跳过条数LIMIT 是返回条数。页码第 2 页时OFFSET 10, LIMIT 10。数据量大时 OFFSET 越翻越慢可以改成WHERE id 上一页最大 id这个优化点答辩时说出来是加分项。4. 连接与数据访问层JDBC、可视化工具和事务让系统真正跑起来4.1 JDBC 连接 MySQL连接串、驱动类与字符集大作业用 Java 写界面的比例最高。Java 连接 MySQL 的第一步是引入驱动。如果你还在用很老的com.mysql.jdbc.Driver遇到 MySQL 8.0 会提示类已废弃或者认证失败应该换成com.mysql.cj.jdbc.Driver对应驱动包 mysql-connector-j 8.x。用 Maven 时依赖坐标类似com.mysql:mysql-connector-j以官方 release 为准。连接串如下Class.forName(com.mysql.cj.jdbc.Driver); String url jdbc:mysql://localhost:3306/library_db ?useSSLfalse serverTimezoneAsia/Shanghai characterEncodingutf8 allowPublicKeyRetrievaltrue; Connection conn DriverManager.getConnection(url, root, 你的密码);逐个参数说明参数作用不写或写错的后果useSSLfalse本地开发不启用 SSL 校验证书校验失败连接报错serverTimezoneAsia/Shanghai明确时区报时区错误或日期差 8 小时characterEncodingutf8让驱动用 UTF-8 传输中文中文乱码allowPublicKeyRetrievaltrue8.0 认证插件首次连接交换公钥连接被拒拿到 Connection 后标准做法是用 PreparedStatement而不要用 Statement 拼字符串。答辩时老师很可能故意问“如果我输入 OR 11 --会怎样”PreparedStatement 能把危险输入当普通字符串处理PreparedStatement ps conn.prepareStatement( SELECT * FROM reader WHERE reader_name LIKE ?); ps.setString(1, % keyword %); ResultSet rs ps.executeQuery(); while (rs.next()) { System.out.println(rs.getString(reader_no)); }这里?占位符取代字符串拼接参数由驱动统一转义。取结果时优先用列名而不是下标表结构改了代码不容易错。用完按 ResultSet、PreparedStatement、Connection 顺序关闭或者用 try-with-resources 自动关闭后者更省心。4.2 图形化工具与 MySQL Workbench/Navicat 的高频操作不愿意写代码调试 SQL 时可以用可视化工具。MySQL Workbench 是官方工具界面稍笨但免破解。Navicat for MySQL 更顺手但它是商业软件网上所谓“破解安装”渠道风险很大别在作业机上下载。我的建议是能接受英文用 Workbench想要中文界面可以用开源的 DBeaver功能完全覆盖。Workbench 的四个高频区域左侧 Navigator 看表中间 SQL 编辑器执行Server 菜单做导出下方 Result Grid 看结果。新建连接只需填 Hostname 127.0.0.1、Port 3306、用户名 root、密码。连接报错分两类一类是网络/服务问题报“Cant connect to MySQL server”检查 mysqld 是否在运行另一类是认证问题报“Unable to load authentication plugin caching_sha2_password”要么升级客户端要么把用户认证插件改回旧版。我习惯用 Workbench 跑临时 SQL用命令行执行正式建表脚本两边对照减少手滑。4.3 事务、连接池和大作业的“生产感”期末大作业最容易显得业余的地方是“点一下按钮数据库就变了没有任何保护”。借书功能至少有两步插入借阅记录减少图书可借数量。如果插入成功但更新失败库存和记录就对不上。下面用 JDBC 手写事务conn.setAutoCommit(false); try { PreparedStatement ps1 conn.prepareStatement( INSERT INTO borrow(reader_id, book_id, borrow_time, due_time) VALUES (?,?,NOW(),DATE_ADD(NOW(), INTERVAL 30 DAY))); ps1.setInt(1, readerId); ps1.setInt(2, bookId); ps1.executeUpdate(); PreparedStatement ps2 conn.prepareStatement( UPDATE book SET available available - 1 WHERE id ? AND available 0); ps2.setInt(1, bookId); int rows ps2.executeUpdate(); if (rows 0) { throw new RuntimeException(库存不足回滚); } conn.commit(); } catch (Exception e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); }这段代码先关闭自动提交两条 SQL 全部成功才 commit任何一步失败就 rollback把插入的借阅记录和减掉的库存一起撤销。UPDATE 里带AND available 0用返回行数判断有没有可借库存比先 SELECT 再 UPDATE 更不容易产生并发缝隙。catch 里不要只打一行e.printStackTrace()就完事至少要把异常信息记录到日志否则现场演示失败时你连哪一步错了都看不到。如果还想向“生产系统”再靠近一步可以引入连接池。MySQL 的数据库连接池常见有 HikariCP、Druid、c3p0。大作业不需要用重型框架但可以说清原理连接池预创建若干条连接用完后归还而不是关闭避免每次请求都重复 TCP 握手。HikariCP 的核心参数是 maximumPoolSize、minimumIdle、connectionTimeout。演示时把 maximumPoolSize 设成 10就能解释“为什么数据库第一次访问慢后面就快了”。5. MySQL期末大作业避坑指南5个高频翻车点的现象、原因与处置5.1 连接报错 ERROR 2002 (HY000)服务没起还是连错了实例现象在命令行执行mysql -u root -p直接报错类似ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock。很多同学以为是密码错了其实这根本没到认证阶段。原因MySQL 客户端默认通过 Unix socket 连接本机报这个错通常说明 mysqld 服务没启动或者 socket 文件路径和配置不一致。如果用 TCP 方式指定-h 127.0.0.1 -P 3306仍然失败再往端口和防火墙方向查。解决先看服务状态。Systemd 环境执行systemctl status mysqld或systemctl status mysql确认 active 后再看配置文件my.cnf里 socket 路径。手动启动实例时可以指定mysqld --socket/tmp/mysql.sock要和客户端预期一致。Windows 下到服务列表里确认 MySQL80 启动。按这个顺序排查能覆盖九成“我密码没错为什么连不上”的问题。5.2 中文乱码和“”从库、表到连接串的逐层排查现象插入中文后 SELECT 出来全是问号或者数据库中看着正常但程序读出来乱码。很多人第一反应是改表字符集改完还在乱码于是怀疑数据库软件有问题。原因字符集要贯穿三层才不丢。第一层是库和表的字符集第二层是客户端会话字符集第三层是 JDBC 或编程语言编码。任何一层是 latin1中文传到下一层就变成问号。MySQL 8.0 默认库字符集是 utf8mb4但如果你建库时不指定又碰上某些镜像改过默认值就会出问题。解决逐层检查。先跑SHOW CREATE TABLE book;看 CHARSET连接后执行SET NAMES utf8mb4;JDBC 连接串加characterEncodingutf8。三层一致后把之前乱码的数据 DELETE 后重新插入。注意连接串里不是写characterEncodingutf8mb4Java 驱动认的是utf8它实际对应 4 字节 utf8写 utf8mb4 反而可能不认识。5.3 MySQL 8.0 认证插件导致工具或老驱动连不上现象Navicat 或老版本 JDBC 连 MySQL 8.0 报Unable to load authentication plugin caching_sha2_password。用户名密码明明正确就是连不进。原因MySQL 8.0 默认新用户的认证插件是 caching_sha2_password而 5.x 时代的工具和驱动只实现了 mysql_native_password。握手时客户端不认服务端插件连接被拒。解决优先升级客户端JDBC 换 mysql-connector-j 8.xWorkbench 换 8.x。如果必须用旧工具单独创建大作业用户并把认证插件指定为旧版CREATE USER testerlocalhost IDENTIFIED WITH mysql_native_password BY 123456; GRANT ALL PRIVILEGES ON library_db.* TO testerlocalhost; FLUSH PRIVILEGES;不建议直接 ALTER 把 root 改成旧插件那是临时兼容手段。大作业本地演示建一个专用用户更干净。另提醒密码别用 123456至少 8 位混合答辩前把 root 密码明文贴在演示文档里并不体面。5.4 UPDATE 或 DELETE 被 Safe Updates 拦住Error 1175现象执行UPDATE book SET available 0;时 MySQL 报错提示使用 Safe Updates 模式拒绝执行。注意是执行前被拦不是执行后回滚。原因图形化客户端默认开启SQL_SAFE_UPDATES 1这是防误操作机制要求 UPDATE 和 DELETE 必须通过主键或唯一键定位防止一条语句改掉全表。解决不要上来就SET SQL_SAFE_UPDATES 0用正确姿势写条件就能通过。例如UPDATE book SET available 0 WHERE id 1;如果确实想批量重置先查出主键范围再写进 WHERE。保留 Safe Updates相当于给自己上一道保险演示时误删全表的尴尬就不会发生。5.5 统计结果翻车ONLY_FULL_GROUP_BY 与 NULL 聚合现象查询“每个读者的借阅数量”时SQL 在某些机器上能跑你的 MySQL 8.0 上报错Expression #2 of SELECT list is not in GROUP BY clause。或者统计时发现 COUNT 少了一行。原因MySQL 8.0 默认启用 ONLY_FULL_GROUP_BYSELECT 里出现的非聚合列必须是 GROUP BY 列或被聚合函数包裹。同学机器上的旧配置可能关闭了该模式所以结果不一致。COUNT 少一行是因为写了COUNT(列名)而该列存在 NULLNULL 不参与计数。解决严格写 SQL。要么让 SELECT 列与 GROUP BY 列保持一致要么把非分组列包进 MAX、MIN、GROUP_CONCAT。统计行数用COUNT(*)统计字段非空个数才用COUNT(field)。这个细节之差就是期末大作业一个明晃晃的扣分点。提前在命令行里把统计 SQL 跑通比现场改 SQL 从容得多。6. 答辩前让 MySQL 大作业“保值”索引、视图与备份恢复三个亲手验证期末大作业不是交完就完答辩时老师大概率会现场翻表、翻 SQL。给你三个我常用的验证动作每个只需几分钟却能让整套东西显得完整。第一个是 EXPLAIN 验证索引。在借阅查询执行前加上EXPLAIN看 type 和 key 字段。例如EXPLAIN SELECT * FROM borrow WHERE reader_id 5 AND return_time IS NULL;如果 type 是 ref、key 是 idx_borrow_status说明之前建的联合索引生效了。就算没生效也可以现场补一条ALTER TABLE borrow ADD INDEX idx_reader_time (reader_id, return_time);再重新 EXPLAIN这个过程本身就很像排障。第二个是留下视图。把“逾期未还列表”封装成一个视图应用层只查视图不写复杂联表CREATE OR REPLACE VIEW v_overdue AS SELECT r.reader_no, r.reader_name, b.title, br.due_time, DATEDIFF(NOW(), br.due_time) AS overdue_days FROM borrow br JOIN reader r ON br.reader_id r.id JOIN book b ON br.book_id b.id WHERE br.return_time IS NULL AND br.due_time NOW();视图在答辩时会被追问“视图是不是占存储空间”记住视图只是逻辑表不存数据底层表变化视图结果跟着变。第三个是备份恢复。用 mysqldump 导出整库mysqldump -u root -p library_db library_db_backup.sql恢复时先建一个空库再把备份导进去mysql -u root -p -e CREATE DATABASE IF NOT EXISTS library_db_restore mysql -u root -p library_db_restore library_db_backup.sql如果是 InnoDB 表导出时加--single-transaction可以避免锁表。恢复后随便查一条记录能对上原库数据即可。我个人的习惯是交作业前把建表、造数、视图、备份四份 .sql 文件分开放每份开头写清楚用途和日期。这既能让老师快速还原环境也能让你在“演示到一半删错了表”时有一份后悔药。期末大作业这个体量不追求高深架构把表设计、事务、索引、备份这些基础动作做扎实就已经超出大部分同学一截。希望帮到你。本文还有配套的精品资源点击获取
返回列表