简介:该资源为《MySQL数据库基础实例教程(第3版)(微课版)》配套源代码压缩包,内含书中例题、商业案例、综合实训及学校实战演练四个项目的SQL脚本与说明文件,适合数据库初学者、自学者及需要提升MySQL应用能力的开发者按章节对照练习。包内共5个文件,以4个sql脚本和1个txt说明文档为主,整体约21KB,用户可通过说明快速定位文件用途,并直接导入脚本还原数据库结构、验证课堂实例与试验综合项目流程。资源由abments整理分享,目前已有115人学习浏览,文件小巧、目录思路清晰,是一份便于快速启动的MySQL入门与实操辅助材料,可结合《MySQL数据库基础实例教程(第3版)》一书同步使用,也可作为课程设计或实训环节的参考脚本,帮助读者将数据库设计、查询优化、备份恢复等知识点落到实际项目场景中。
1. 拿到一份 MySQL 教材源码包,先别急着解压:它到底能帮你学会什么
你手上这个64402-MySQL数据库基础实例教程(第3版)(微课版)-源代码(含例题、案例、实训、实战四个项目).zip.zip,名字已经把内容说得很清楚:它不是安装包,也不是某个现成的网站后台,而是一套跟着课本走的 MySQL 教学源码。外层 zip 解开后往往还会再得到一个 zip,很多人第一次解压后双击发现还是一堆压缩文件,以为下载坏了,其实这是教材配套资源常见的打包方式。
这套源码解决的核心问题,是“书看懂了,但一开终端就卡住”。教材里的 SQL 一行行抄进命令行能跑,但换到完整的建库脚本、多表查询、存储过程和工程调用时,新手经常连文件先执行哪个都不知道。例题、案例、实训、实战四层结构,正好是从“跟读语法”到“独立做一个数据库应用”的台阶。适合刚装好 MySQL 还想把知识落地的初学者,也适合准备数据库课程设计、需要快速搭一个选题原型的在校生。
我建议先不要急着把所有文件一次性导进数据库。拿到代码之后,先搭一个可控的本地 MySQL 环境,再按照“环境 → 目录结构 → 实战数据链路 → 排错 → 改造”的顺序推进。下面每一章都按这个路径展开,最后你会得到一套能跑、能改、能给别人讲清楚的数据库实训源码。
2. 搭好能跑这套源码的 MySQL 环境:版本选择与最小安装配置
2.1 为什么教材源码最容易卡在版本差异上
MySQL 5.7 和 MySQL 8.0 在表面上都是mysql,实际行为差异足以让同一段教学源码“这边能跑,那边报错”。我处理过的教材配套代码里,最常见的三类问题都出在版本差异上。
第一是默认字符集。5.7 默认是utf8,8.0 默认是utf8mb4;如果源码建表语句没写DEFAULT CHARSET,导入 8.0 后中文宽度、排序规则都可能不一样。第二是认证插件。教材配套代码常用老式mysql_native_password,但 MySQL 8.0 默认用caching_sha2_password,老版本的 JDBC、PHP 或可视化工具很可能在连接阶段就直接报认证失败。第三是sql_mode,尤其ONLY_FULL_GROUP_BY在 8.0 默认开启,导致教材里常见的SELECT * FROM student GROUP BY class_name直接报 1055 错误。
我把几个关键差异整理成了对照表,导入前先对着查一遍,能省掉后面大半排错时间:
| 影响点 | MySQL 5.7 | MySQL 8.0 | 源码里的典型症状 |
|---|---|---|---|
| 默认字符集 | utf8 | utf8mb4 | 中文乱码、字段长度超限 |
| 密码认证 | mysql_native_password | caching_sha2_password | 客户端报 unable to load authentication plugin |
| GROUP BY | 默认不强制 ONLY_FULL_GROUP_BY | 默认强制 | ERROR 1055,select 列不在 group by 中 |
| 窗口函数 | 不支持 | 支持 | 8.0 新语法在老版本里直接报语法错 |
| 公用表表达式 WITH | 不支持 | 支持 | 解析到 WITH 处报语法错 |
所以搭建环境的第一个原则是:先确认源码面向哪个版本,再去选安装方式。如果没有特别说明,我会优先用 MySQL 8.0 的稳定小版本,因为它仍然兼容大多数教学 SQL;只有当你实测发现某段脚本用到了 5.7 专有行为、且升级改写成本太高时,再切回 5.7 做对照。
2.2 在 Ubuntu 上用最小命令装好 MySQL 并验证
常见的教材演示环境是 Windows,但服务器和面试机大多是基于 Linux。我建议至少在 Linux 上跑一遍完整安装流程,这本身就是一次 MySQL 基础能力训练。如果你目前只有 Windows,可以先装 WSL 再执行下面命令,过程基本一致。
下面是一套最小安装命令,适用于 Ubuntu 22.04 或 24.04:
# 先更新软件索引,再安装服务端与客户端 sudo apt update sudo apt install -y mysql-server mysql-client # 查看版本,确认服务已经在运行 mysql --version systemctl status mysql --no-pager | head -n 5 # Ubuntu 默认 root 走 auth_socket,用 sudo 进入 MySQL shell sudo mysql -u root -e "SELECT VERSION();"这段命令的关键点有三处。apt install -y mysql-server mysql-client会同时装上服务端和命令行客户端;systemctl status mysql | head -n 5只看前几行,能快速确认 active (running);最后的sudo mysql -u root是因为 Ubuntu 仓库里的 MySQL 默认 root 认证方式是auth_socket,只有系统 root 或 sudo 用户才能登录,直接mysql -u root -p会得到 1045 权限拒绝。
如果要让后续 JDBC、Python、教材配套程序用账号密码连接,需要给 root 设置一个本地密码。常见做法是:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPass123'; FLUSH PRIVILEGES; SELECT user, host, plugin FROM mysql.user WHERE user='root';这里把认证方式显式改成了mysql_native_password,是为了兼容老教材里的连接配置。副作用是 MySQL 8.0 官方不再推荐这个插件,所以如果你后续用的驱动和工具都较新,可以直接写ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourPass123';,让它走默认的caching_sha2_password,更安全,也更接近生产环境。
2.3 用 Docker 临时起一个 5.7 环境做版本对照
有些源码里的存储过程或分组查询在 MySQL 5.7 里跑得很顺,放到 8.0 就报错。与其反复改本机环境,不如用 Docker 起一个一次性实例,端口映射到 3307,避免和本机 3306 冲突。
# 创建 MySQL 5.7 容器,root 密码设为 root,宿主机访问端口 3307 docker run --name mysql57 \ -e MYSQL_ROOT_PASSWORD=root \ -p 3307:3306 \ -d mysql:5.7 # 验证容器里的版本 mysql -h127.0.0.1 -P3307 -uroot -proot -e "SELECT VERSION();"参数说明:--name mysql57是容器名,后面用docker start/stop mysql57管理;-e MYSQL_ROOT_PASSWORD=root给容器初始化 root 密码;-p 3307:3306把容器内部的 3306 映射到宿主机的 3307,避免与本地 MySQL 冲突。最后的连接命令里,-h127.0.0.1必须写,因为要走 TCP 协议而不是默认 socket。
我一般会用这个容器专门验证“5.7 能跑、8.0 不能跑”的脚本。把源码里的 SQL 文件分别导进两个实例,用同一套查询语句对比结果,这样就不用在两个本机版本之间反复卸载安装了。环境准备好之后,下一步才是真正打开源码包。
3. 四层项目目录怎么消化:例题、案例、实训、实战各学一遍
3.1 先给源码包做“体检”:解压、看目录树、找 SQL 入口
拿到源码后第一件事不是双击打开,而是先把它放到一个干净目录里,然后再看结构。因为外层 zip 内层还套了一个 zip,很多人在 Windows 上直接右键解压,得到的是“文件名带中文的套娃压缩包”,后面命令行操作会因为引号和编码问题变得很痛苦。
在 Linux 或 WSL 下,我一般这样解压:
# 第一层解压时指定 GBK 编码,避免中文文件名乱码 unzip -O gbk "64402-MySQL数据库基础实例教程(第3版)(微课版)-源代码(含例题、案例、实训、实战四个项目).zip.zip" # 再解压内层 zip,放到 src 目录 unzip -O gbk "64402-MySQL数据库基础实例教程(第3版)(微课版)-源代码(含例题、案例、实训、实战四个项目).zip" -d ./src # 只看目录,不看文件,确认四层结构 find ./src -maxdepth 2 -type d | sort # 列出所有 SQL 文件,看看入口脚本长什么样 find ./src -name "*.sql" -type f | sort | head -n 20参数说明:-O gbk让 unzip 用 GBK 编码解析压缩包内的中文文件名,这是处理国内教材 zip 最常用的一招;-d ./src指定解压目标目录;find -maxdepth 2 -type d只显示两层目录,够看到“例题、案例、实训、实战”四个顶层项目,又不会被几百个文件刷屏。
拿到目录列表后,不要着急点进某个子目录。先看是否有顶层 README、建库脚本、样例数据文件。任何教学源码,哪怕文件组织再乱,通常都会有这几类入口:create_database.sql负责建库、create_table.sql负责建表、insert_data.sql负责造样例数据,剩下的就是各个章节例题和项目代码。
3.2 批量导入 SQL:从建库到造数的最小执行顺序
很多新手拿到一包.sql文件就执行mysql < 全部文件.sql,结果不是报“表不存在”,就是数据导进了错误的库。教材源码里,建库脚本和业务脚本往往分散在四个项目目录中,直接全量导入会让 MySQL 不知道该把表建到哪个库。
我建议按“先建库,再建表,最后导数据”的顺序手动控制:
# 建库,字符集统一指定 utf8mb4 mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS school DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 导入建表结构 mysql -uroot -p school < ./src/案例/create_table.sql # 导入基础数据 mysql -uroot -p school < ./src/案例/insert_data.sql # 验证核心表 mysql -uroot -p school -e "SHOW TABLES;"逻辑说明:第一步用-e直接执行一条建库语句,IF NOT EXISTS避免重复执行报错;字符集写成utf8mb4,基本覆盖教材业务里的中文数据。第二步和第三步用<把外部 SQL 文件输入到mysql客户端,并指定默认数据库school,这样即使文件内部没有写USE school,表也会落到正确位置。最后用SHOW TABLES确认结构导入成功。
这里有一点容易忽略:如果 SQL 文件内部已经写了USE xxx,那么命令行里指定的school会被文件内的USE覆盖。所以我执行前会先看一眼文件头,确认它有没有自带USE。如果自带,我会把mysql命令行改成不带数据库名执行:
mysql -uroot -p < ./src/案例/create_table.sql这样反而不会被默认数据库干扰。
3.3 例题和案例的学习节奏:先补基础再动手
例题目录通常对应教材里每一章的短 SQL,比如SELECT、INSERT、UPDATE、DELETE语法。这些脚本往往只有一两行,夹在复杂项目代码里很容易被忽略,但它们却是整个数据库增删改查的最小单元。
我的建议是:不要用source一次性跑完整个例题文件,而是在 MySQL Workbench 或命令行里逐句执行,观察影响行数和返回结果。命令行里可以用-e加-t让结果以表格形式显示:
mysql -uroot -p school -e "SELECT student_id, name, class_name FROM student LIMIT 10;"-t让输出对齐成 ASCII 表格,适合看查询结果;LIMIT 10避免一次返回太多行。遇到UPDATE和DELETE这类写操作,我习惯先开事务,再执行,然后决定提交还是回滚:
START TRANSACTION; UPDATE account SET balance = balance - 50 WHERE student_id = '2023001'; SELECT * FROM account WHERE student_id = '2023001'; ROLLBACK;这个例子背后是教材里最常见的业务:账户扣款。把一整条课程源码拆成“先查再改、改完可撤销”的流程,比直接执行源码里的裸UPDATE安全得多,也能真正理解事务的后悔药作用。案例目录则不同,它通常是章节末尾的完整场景,比如学生选课、图书借阅或商品订单。案例里的 SQL 往往有多表 JOIN、外键约束和视图,适合整段导入后做 EXPLAIN 分析:
EXPLAIN SELECT s.name, c.course_name, sc.score FROM student s JOIN score sc ON s.student_id = sc.student_id JOIN course c ON c.course_id = sc.course_id WHERE sc.score < 60;EXPLAIN不真正执行查询,而是返回 MySQL 的执行计划。读结果时重点看type、key、rows三列:type从ALL变成ref或eq_ref,说明 JOIN 用上了索引;key显示实际用到的索引名;rows是估计扫描的行数。教材案例里数据量小,扫描多少行都不慢,但养成看执行计划的习惯,后面做实训和实战项目才不会写出“能跑但没法解释”的 SQL。
4. 把实战项目跑成一条数据链路:建表、造数、查询、存储过程
4.1 先读懂实战项目的数据字典,再碰 SQL
实战项目目录和例题、案例最大的区别,是它不再围绕单个知识点,而是围绕一个完整业务。常见选题包括学生成绩管理、图书借阅、进销存、员工薪资等。想要把项目跑通,第一件事不是执行代码,而是从建表脚本里提炼出一份数据字典。
数据字典不需要做得多花哨,能回答四个问题就够了:有哪些表、每张表存什么、表之间靠哪个字段关联、哪些字段有默认值或唯一约束。我一般用表格把 CREATE TABLE 脚本里的COMMENT、PRIMARY KEY、FOREIGN KEY手工抄出来:
| 表名 | 核心字段 | 类型 | 约束 | 关联说明 |
|---|---|---|---|---|
| student | student_id | varchar(20) | 主键 | 被 score 引用 |
| course | course_id | varchar(20) | 主键 | 被 score 引用 |
| score | student_id, course_id, score | varchar, varchar, decimal | 联合主键 | 关联 student 与 course |
| account | account_id, balance | int, decimal | 默认余额为 0 | 按业务扩展 |
这张表对应的就是教材实战里最常见的三条核心表:学生、课程、成绩。注意score表用student_id + course_id做联合主键,这保证同一个学生同一门课只有一条成绩记录。如果你拿到的实战项目是订单类或库存类,换成“订单表、订单明细表、商品表”也是同样的套路。
从源码里抄这张字典表只需要几分钟,但价值很大:后面写多表查询、存储过程和触发器时,字段名不会记混,也不会出现WHERE sc.student_id = s.id这种手滑写错关联字段的隐蔽问题。
4.2 从建表脚本到初始化数据,再到业务查询的调试顺序
实战项目的运行链路通常是:建库建表 → 写基础数据 → 跑业务查询 → 通过应用层调用。很多初学者跳过了前两步,直接打开某个 Java 或 Python 文件运行,结果因为数据库里没有表而报 1146。正确的顺序是先让数据库侧的数据链路通,再让程序侧连上来。
数据库侧最小链路是这样的:
-- 建表 CREATE TABLE student ( student_id VARCHAR(20) PRIMARY KEY, name VARCHAR(50) NOT NULL, class_name VARCHAR(50), created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 造数据 INSERT INTO student (student_id, name, class_name) VALUES ('2023001', '林晓', '计算机2301'), ('2023002', '张弛', '计算机2301');逻辑说明:PRIMARY KEY定义主键;NOT NULL约束了姓名不能为空;DEFAULT CURRENT_TIMESTAMP让创建时间自动取当前时刻,这是教材源码里很常见的写法。先跑建表再跑插入,不用担心主键冲突或字段不存在。
数据库侧数据就绪后,就可以用 Python 这类脚本语言做应用侧验证。为什么用 Python?因为教学实战项目里 Java 版本和 JDK 环境太容易翻车,而 Python 配上 pymysql 可以最快地验证数据库连接和查询逻辑:
# 用 pymysql 连接实战项目数据库 import pymysql conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="YourPass123", database="school", charset="utf8mb4", ) try: with conn.cursor() as cur: cur.execute( "SELECT s.student_id, s.name, ROUND(AVG(sc.score), 2) AS avg_score " "FROM student s " "JOIN score sc ON s.student_id = sc.student_id " "GROUP BY s.student_id, s.name " "HAVING AVG(sc.score) < 60" ) for row in cur.fetchall(): print(row) finally: conn.close()参数说明:host、port、user、password、database分别对应 MySQL 的连接地址、端口、账号、密码和默认库;charset="utf8mb4"必须与建库时的字符集一致,否则程序里的中文可能乱码。SQL 里用JOIN关联三张表,ROUND(AVG(score), 2)算平均分并保留两位小数,GROUP BY按学生分组,HAVING过滤出平均分低于 60 的学生。注意GROUP BY后面的字段必须和SELECT里的非聚合字段一致,在 MySQL 8.0 里漏掉任何一个都会直接报 1055。
4.3 存储过程和触发器:先看懂调用,再改参数
实战项目相比案例,通常会多用存储过程和触发器。存储过程把一段业务逻辑封装成“黑匣子”,调用方只要传参数,不需要关心内部 SQL。教材源码里的存储过程一般写在以DELIMITER开头的 SQL 文件里,因为单个;会被 mysql 客户端当作语句结束,必须临时把分隔符改成$$。
看一个最典型的统计存储过程:
-- 删除同名存储过程,避免重复创建报错 DROP PROCEDURE IF EXISTS get_student_count_by_class; -- 临时把分隔符改为 $$ DELIMITER $$ CREATE PROCEDURE get_student_count_by_class( IN cls VARCHAR(20), OUT cnt INT ) BEGIN SELECT COUNT(*) INTO cnt FROM student WHERE class_name = cls; END$$ -- 恢复默认分隔符 DELIMITER ; -- 调用存储过程 SET @cnt = 0; CALL get_student_count_by_class('计算机2301', @cnt); SELECT @cnt;逻辑说明:IN cls VARCHAR(20)是输入参数,调用时传入班级名称;OUT cnt INT是输出参数,存储过程把统计结果写进cnt;SELECT COUNT(*) INTO cnt将聚合结果赋给输出变量。执行到END$$时,因为分隔符是$$,整个流程被当成一条完整语句,而不是按行拆开执行。最后的CALL语句演示了如何传入值和取回结果。
这里有个非常容易踩的坑:DELIMITER $$只是 mysql 客户端的命令,不是 MySQL 服务器语法。如果你在 Python 的 pymysql 或 Java 的 JDBC 里直接执行这段文本,会被服务器当成语法错误。解决办法是应用侧调用存储过程时不要带DELIMITER,直接执行整个CREATE PROCEDURE文本,或者分成多条语句让驱动一次性提交。
触发器在实战项目里通常用于审计或联动更新,比如学生删除后自动清理成绩:
DROP TRIGGER IF EXISTS after_student_delete; DELIMITER $$ CREATE TRIGGER after_student_delete AFTER DELETE ON student FOR EACH ROW BEGIN DELETE FROM score WHERE student_id = OLD.student_id; DELETE FROM account WHERE student_id = OLD.student_id; END$$ DELIMITER ;这段触发器的作用是:只要student表里有记录被删除,就自动把该学生在score和account表中的关联记录一并清掉。AFTER DELETE ON student表示删除动作成功后触发;OLD.student_id是删除前那一行的旧值,MySQL 8.0 里不能用NEW.student_id取删除后的值。跑通这些存储过程和触发器后,实战项目的数据链路才算真正闭合。
5. 跑通源码路上的排查手册:字符集、路径、权限和版本差异
5.1 中文乱码与 1366:先查三层字符集,别急着改表
现象:导入 SQL 文件后,SELECT查出来中文全是问号,或者插入中文时报ERROR 1366 (HY000): Incorrect string value。
原因:MySQL 的字符集分三层:服务器层、数据库层、连接层。教材源码建库时可能没写DEFAULT CHARSET,或者 SQL 文件里写的是latin1,而你的命令行连接默认是utf8mb4,三层只要有一层不一致,中文就可能出问题。
解决:先确认当前各层字符集,再统一入口:
SHOW VARIABLES LIKE 'character_set_%'; SHOW VARIABLES LIKE 'collation_%';执行后重点看character_set_database和character_set_connection。如果数据库是latin1,可以把表转换成 utf8mb4:
ALTER TABLE student CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;ALTER TABLE ... CONVERT TO CHARACTER SET会转换表内所有字符型列的编码。如果表里已经有中文乱码数据,转换只能保证以后不再加剧,改不回已经损坏的内容。所以更可靠的做法是:建库时显式写DEFAULT CHARACTER SET utf8mb4,导入时用mysql --default-character-set=utf8mb4,三层统一后再谈其他。
5.2 连接报 2002 或 1045:是服务没起、socket 找错,还是 root 权限被卡
现象:执行mysql -uroot -p后提示ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock',或者报ERROR 1045 (28000): Access denied for user 'root'@'localhost'。
原因:2002 通常是服务没启动,或者客户端按默认/tmp/mysql.sock找不到 socket,而 Debian/Ubuntu 的 MySQL 默认 socket 路径是/var/run/mysqld/mysqld.sock。1045 通常是密码错误,或者 root 走了auth_socket,你用密码登录当然进不去。
解决:先看服务状态,再决定走 socket 还是 TCP:
sudo systemctl status mysql sudo systemctl start mysql # 强制走 TCP,绕过 socket 路径问题 mysql -h127.0.0.1 -P3306 -uroot -p # 显式指定 socket 路径 mysql -uroot -p --socket=/var/run/mysqld/mysqld.sock-h127.0.0.1 -P3306让客户端走 TCP 而不是 unix socket,适合排查 socket 路径不一致;--socket=则直接把路径写死。如果 1045 依旧存在,最稳妥的方式是从系统 root 进入后重新改认证方式:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPass123'; FLUSH PRIVILEGES;这条命令把 root 改成密码登录,并刷新权限。注意这里的FLUSH PRIVILEGES在ALTER USER之后不是必须的,但写上无害,也能让连带修改的授权立刻生效。
5.3 LOAD DATA 报 1290:源码里的文件路径为什么一跑就翻车
现象:实战项目里有LOAD DATA INFILE '/home/user/data.csv' INTO TABLE student,一执行就报ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option。
原因:为了安全,MySQL 默认只允许从secure_file_priv指定的目录读取文件。源码里写死的路径往往是你当前电脑上的某个目录,和服务器允许读取的目录不一致。
解决:先查允许目录,然后把数据文件放进去:
SHOW VARIABLES LIKE 'secure_file_priv';如果结果是/var/lib/mysql-files/,就把 csv 文件复制过去:
sudo cp /home/you/data.csv /var/lib/mysql-files/ mysql -uroot -p school -e "LOAD DATA INFILE '/var/lib/mysql-files/data.csv' INTO TABLE student FIELDS TERMINATED BY ','"FIELDS TERMINATED BY ','告诉 MySQL 每列之间用逗号分隔。更省事的替代方案是用LOAD DATA LOCAL INFILE,它读取的是客户端本机文件,不受服务端secure_file_priv限制,但需要客户端连接时开启local_infile:
SET GLOBAL local_infile = ON; LOAD DATA LOCAL INFILE '/home/you/data.csv' INTO TABLE student;LOAD DATA LOCAL在安全要求较高的生产环境里常被禁用,所以教学项目里能改路径就别急着开全局开关。
5.4 1055 与认证插件报错:5.7 源码硬跑 8.0 的典型症状
现象:执行SELECT * FROM student GROUP BY class_name时报ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause;或者程序连接时报认证插件错误。这两个问题经常同时出现在同一套教材源码上。
原因:MySQL 8.0 默认开了ONLY_FULL_GROUP_BY,它要求SELECT里出现的非聚合列必须出现在GROUP BY里。5.7 时代的教学代码没遵守这个规则,在 8.0 下自然报错。认证插件同理,8.0 默认插件是caching_sha2_password,旧驱动只认mysql_native_password。
解决:先看当前sql_mode,再在当前会话临时放宽:
SELECT @@sql_mode; SET sql_mode = 'STRICT_TRANS_TABLES';@@sql_mode查全局变量,SET sql_mode只影响当前会话,重启后恢复。这样改适合教学验证,不建议直接改全局,因为ONLY_FULL_GROUP_BY在真实项目里能帮你提前暴露不规范 SQL。认证插件的问题,优先把 JDBC 或 pymysql 升级到新版本,新驱动能识别caching_sha2_password;如果确实改不了驱动,再执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPass123';把 root 切回旧插件,仅作为兼容兜底。
5.5 外键导入顺序错乱:一条 SET 语句解决,但别依赖它上线
现象:导入完整 SQL 文件时,数据量不大但报ERROR 1451 (23000): Cannot add or update a child row: a foreign key constraint fails,明明每一行看起来都正常。
原因:外键约束要求父表中的记录必须先存在。教材源码里的 INSERT 语句可能先插子表再插父表,或者你把多个模块的 SQL 文件按名称排序后挨个导入,顺序恰好颠倒。
解决:在导入前临时关闭外键检查,导入后立刻恢复:
SET FOREIGN_KEY_CHECKS = 0; SOURCE /path/to/全部数据.sql; SET FOREIGN_KEY_CHECKS = 1;SET FOREIGN_KEY_CHECKS = 0让 MySQL 暂不校验外键关系,数据全部落库后再开回来。但要注意:这个开关只是把校验延后,不是修复数据。如果最终子表里有外键指向不存在的父表,恢复检查后后续操作依然会报错。所以导入完必须跑一条关联校验,比如:
SELECT COUNT(*) FROM score sc LEFT JOIN student s ON sc.student_id = s.student_id WHERE s.student_id IS NULL;如果结果为 0,说明外键关系完整,这次的关闭操作只是绕开导入顺序问题,没有造成数据损坏。
6. 把这套源码改造成实训作业和面试题:三个能复用的做法
6.1 把例题里的固定条件改成参数化查询,做成练习题
教材例题里的 WHERE 条件基本是写死的,比如WHERE student_id = '2023001'。我会把这类例题改造成带占位符的 Python 查询,让使用者从终端输入条件,顺便检查参数化写法:
cur.execute( "SELECT * FROM student WHERE class_name = %s AND score >= %s", (cls, min_score) )%s是占位符,参数放在第二个参数的元组里,由驱动负责转义,避免拼接 SQL 带来的注入风险。改造完之后,这份源码就从“跟读练习”变成“可验收的实训作业”。
6.2 用 mysqldump 把实训库变成可备份、可迁移的环境
与其专门找数据库同步工具,不如先学会用一个标准命令完成最轻量的迁移:mysqldump。我会在实战项目跑通后立刻做一次全库导出:
mysqldump -uroot -p school > school_backup.sql mysql -uroot -p school < school_backup.sql第一句导出结构加数据,第二句导入到另一个实例。这一步看起来简单,却能验证你配置的字符集、权限和默认库是否经得起从笔记本迁到服务器的过程。需要增量同步时,再考虑基于 binlog 的主从复制,但基础迁移必须先从mysqldump开始。
6.3 给实战项目补一个造数存储过程,验证报表逻辑
教材自带数据往往只有二三十行,跑聚合和排名看不出效果。我会在源码基础上补一个造数存储过程,用于批量生成成绩数据,然后观察窗口函数和分页查询:
DROP PROCEDURE IF EXISTS generate_scores; DELIMITER $$ CREATE PROCEDURE generate_scores(IN loops INT) BEGIN DECLARE i INT DEFAULT 0; WHILE i < loops DO INSERT INTO score(student_id, course_id, score) VALUES ( 1 + (i % 30), 1 + (i % 10), ROUND(50 + RAND() * 50, 0) ); SET i = i + 1; END WHILE; END$$ DELIMITER ; CALL generate_scores(1000);loops控制插入行数;student_id和course_id用1 + (i % n)在已有主键范围内循环,避免外键冲突;RAND() * 50生成 50 到 100 之间的随机成绩。造完数后再跑RANK()、DENSE_RANK()、LIMIT分页,就能看出数据量对查询结果的影响。
我自己的习惯是:每拿到一套教学源码,先按“环境、目录、链路、排错、改造”走完一遍,然后删库重来一次。第二次不查笔记也能独立跑通,这份源码才算真正变成了你的能力。希望帮到你。
本文还有配套的精品资源,点击获取