简介这是一份头歌MySQL数据库实训的答案整理文档面向正在完成头歌平台实训作业的学生也适合需要系统回顾MySQL核心操作的初学者。文档以PDF格式提供共1个文件压缩包大小433KB配有目录结构可快速跳转到对应关卡。上线以来已有18363人学习内容覆盖数据库定义、数据表创建、约束应用、表结构修改等实训模块包含主键约束、外键约束、唯一约束、默认值及自增列等关键用法。答案按实训关卡顺序编排每一步均给出完整可运行的SQL语句例如CREATE DATABASE、CREATE TABLE、ALTER TABLE、DESCRIBE等在数据库与表的基本操作部分还细化到查看表结构、修改表名、修改字段名与数据类型、添加与删除字段、调整字段排列位置、删除外键约束、插入与更新数据等具体场景。特别是复合主键、外键关联、字段改名等易错点均做了清晰整理方便读者对照实操、排查问题与考前复习。1. 头歌MySQL数据库实训答案一份能照着提交的题解帮你把评测关卡刷通关头歌MySQL数据库实训最磨人的不是SQL语法本身而是平台的评测机制它只比对最终输出不关心你的过程写了多少注释、用了什么别名。这份带目录的PDF从初识MySQL一路排到存储过程每一关都给了可以复制的命令我在逐条核对过程中发现它覆盖了建库建表、约束应用、表结构修改、增删改、单表查询、连接查询、子查询、聚合函数、视图、索引和存储过程基本把实训课上的硬骨头都啃了一遍。适合三类人在头歌上被评测卡住的在校生、考前突击刷题的人、想用最短时间把MySQL核心命令过一遍的转行者。整理者在资源前言里标了反馈渠道个别关卡的代码有复制笔误下面我会把踩过的坑一并标出来。2. 建库建表与约束从CREATE DATABASE到外键约束的实操拆解2.1 登录命令与创建数据库三个参数先搞清楚再动手资源里反复出现的登录命令是这一条mysql -uroot -p123123 -h127.0.0.1 create database MyDb;拆开看参数-u 指定用户名root 是 MySQL 默认超级用户-p 后面直接跟密码 123123中间没有空格这是 MySQL 命令行客户端的惯用写法如果你写成 -p 123123MySQL 会把它当成提示输入密码的占位符而不是直接用 123123-h 指定连接的主机地址127.0.0.1 是本地回环地址。整个命令在实训容器里执行时默认端口一般是 3306所以不用写 -P如果换到你自己的 Windows 本机且 MySQL 改过端口就得补上 -P 参数。执行 create database MyDb; 之前我建议先用 show databases; 看一眼实例里已经有哪些库。实训环境经常给你预置了同名数据库如果评测要求新建而库里已经存在MySQL 会报 database exists 的错误。原文档用的是 MyDb 这个大小写混合的名字在 Linux 环境下库名是区分大小写的后面用 use MyDb; 时必须保持同样的大小写一旦写成 use mydb; 就会报错。这个细节在多个关卡里都出现过是初赛最常见的丢分点。2.2 建表与主键约束字段类型和约束声明的位置都有讲究第2关创建表的答案是这样的create database TestDb; use TestDb; create table t_emp ( id int, name varchar(32), deptId int, salary float );这条建表语句没有加任何约束纯粹定义字段名和类型。int 是整数类型varchar(32) 是可变长字符串最多存 32 个字符float 是单精度浮点。MySQL 里 int、varchar、float 都不区分大小写写成 INT、VARCHAR、FLOAT 也一样能用但字段名建议统一小写方便后面所有关卡复用。注意 use TestDb; 和 create table 必须连着执行如果你省掉 use 语句直接建表表会被建到默认数据库里后面 SELECT 时就会报表不存在。第3关主键约束给出了两条建表语句create table t_user1 ( userId INT PRIMARY KEY, name VARCHAR(32), password VARCHAR(11), phone VARCHAR(11), email VARCHAR(32) ); create table t_user2 ( name VARCHAR(32), phone VARCHAR(11), email VARCHAR(32), PRIMARY KEY(name, phone) );t_user1 用的是列级主键约束直接在 userId 字段后面写 PRIMARY KEY表示这一列是唯一标识不能为空且不能重复。t_user2 用的是表级联合主键PRIMARY KEY(name, phone) 把 name 和 phone 合起来作为主键含义是只要 name 和 phone 的组合不重复就允许插入。从实践角度看联合主键在业务表里很常见比如同一姓名可能重名加上手机号就能锁定唯一用户。联合主键的字段顺序会影响索引命中把查询最常用的字段放前面这是后边组合索引的最左前缀原则的雏形。2.3 外键约束与常用约束两张表的字段类型必须对齐外键约束这一关的建表语句是这样CREATE TABLE t_class ( id INT PRIMARY KEY, name VARCHAR(22) ); CREATE TABLE t_student ( id INT PRIMARY KEY, name VARCHAR(22), classId int, CONSTRAINT fk_stu_class1 FOREIGN KEY(classId) REFERENCES t_class(id) );外键的核心约束是子表 t_student 的 classId 字段只能填 t_class 表 id 字段里已经存在的值。CONSTRAINT fk_stu_class1 是给这个外键起名字之后如果要删外键DROP FOREIGN KEY 后面跟的就是这个名字。一个非常容易翻车的地方是被 REFERENCES 的字段必须有索引或是主键t_class 的 id 是主键所以没问题另外两边字段类型必须完全一致如果 t_class.id 是 INT 而 t_student.classId 是 VARCHAR建表会直接报 ERROR 1215我见过不少人在这一步把类型写岔然后卡一整关。资源里原题代码在 t_class 建表语句末尾多了个右括号直接复制会报语法错误照着上面的写法去掉多余括号就行。第5关添加常用约束CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32) NOT NULL UNIQUE, sex VARCHAR(4) DEFAULT 男 ) DEFAULT CHARSETutf8;这条语句集中展示了三种约束NOT NULL 表示 username 不能为空UNIQUE 表示用户名不能重复DEFAULT 男 表示插入时如果不给 sex 字段赋值自动填 男。AUTO_INCREMENT 是自增主键每插入一行自动加 1不用手动赋值。DEFAULT CHARSETutf8 是表级属性指定表默认字符集为 utf8实训题里要求中文数据正常显示时这个参数务必保留在 MySQL 5.6 之前的老版本里写成 ENGINEInnoDB DEFAULT CHARSETutf8 也很常见InnoDB 是支持事务和外键的默认存储引擎MyISAM 不支持外键后面做外键关卡时要注意区分。3. 表结构修改与数据操作ALTER和DML的实操细节3.1 ALTER TABLE 的五种修改操作改名、改字段、增删列各有各的写法数据库和表的基本操作一这一大关全部围绕 ALTER TABLE 展开。先看改名和查看结构ALTER TABLE tb_emp RENAME jd_emp; show tables; describe jd_emp;ALTER TABLE ... RENAME 在 MySQL 8.0 里等价于 RENAME TABLE tb_emp TO jd_emp两种写法都行。改完名之后用 show tables 确认表已经出现在库中再用 describe 查看字段结构。describe 可以简写成 desc在头歌评测里两种都接受但我建议统一写全称有的关卡输出比对严格简写可能在个别环境里不认。修改字段名和数据类型ALTER TABLE tb_emp change Id prod_id int(11); ALTER TABLE tb_emp MODIFY Name varchar(30);这里有个非常关键的区别CHANGE 和 MODIFY 都能改字段但 CHANGE 可以同时改字段名和类型语法是 CHANGE 旧字段名 新字段名 新类型即使只改类型不改名字也要把旧名字和新名字各写一遍MODIFY 只能改类型和属性不能改字段名所以省掉了重复写字段名。做题时凡是题目说把 Id 改为 prod_id 且类型改为 int(11)就用 CHANGE只说把 Name 的类型改成 varchar(30)用 MODIFY 更保险。int(11) 里的 11 是显示宽度不是存储长度括号里写多大都不影响实际存储范围。添加与删除字段ALTER TABLE tb_emp ADD Country varchar(20) AFTER Name; ALTER TABLE tb_emp DROP Salary;ADD 默认把新字段追加到表末尾AFTER Name 指定插到 Name 字段后面FIRST 则插到第一列。DROP Salary 是整列删除该列的所有数据会一并删掉这个操作不可逆。实训环境里表是临时创建的所以无所谓但如果同样的语句拿到生产库上执行前一定要先备份我一般会先 CREATE TABLE 备份表 AS SELECT * FROM 原表再动手。修改字段排列位置ALTER TABLE tb_emp MODIFY Name varchar(25) FIRST; ALTER TABLE tb_emp MODIFY DeptId int(11) AFTER Salary;MODIFY 除了改类型还能配合 FIRST 和 AFTER 调整字段顺序。这里有个必踩的坑MODIFY 必须把该字段的完整定义写全包括类型和长度你只写 MODIFY Name FIRST 不写 varchar(25)MySQL 会直接报错因为服务器需要知道调整位置后这个字段是什么类型。这是 ALTER 关卡里翻车率最高的一条我每次都会先 DESCRIBE 一下当前结构确认目标字段的完整类型定义再写 MODIFY。3.2 插入、更新、删除数据DML三件套的边界要拎清数据库和表的基本操作二整章是 DML。先看多行插入INSERT INTO tb_emp(Id,Name,DeptId,Salary) VALUES (1,Nancy,301,2300.00), (2,Tod,303,5600.00), (3,Carly,301,3200.00);值列表用逗号分隔一条语句插入三行比逐行 INSERT 高效。字符串可以用单引号也可以用双引号MySQL 默认两种都接受但 ANSI 标准推荐单引号头歌评测两种都认。字段名括号里的顺序决定 VALUES 里每个值的含义如果表定义里的字段顺序正好是 Id,Name,DeptId,Salary可以直接 INSERT INTO tb_emp VALUES(...)但一旦中间有自增列或默认值列不写字段名就很容易错位所以实训里建议始终把字段名写上。条件更新和条件删除UPDATE tb_emp SET NameTracy,DeptId302,Salary4300.00 WHERE id3; DELETE FROM tb_emp WHERE Salary3000;UPDATE 不带 WHERE 会更新全表所有行DELETE 不带 WHERE 会清空整表这是 SQL 新手最容易写出的两个灾难级操作。实训题里给出的条件通常很明确WHERE id3 只改第三行WHERE Salary3000 删掉工资超过 3000 的记录。我这里给你一个自己用了很久的习惯写完 UPDATE 和 DELETE先跑一遍等价的 SELECT 确认锁定的行数比如 UPDATE 前先 SELECT * FROM tb_emp WHERE id3;DELETE 前先 SELECT COUNT(*) FROM tb_emp WHERE Salary3000;确认无误再执行这个习惯能救回不少分数。3.3 删除外键与ALTER的执行顺序删除表的外键约束这一关给了一条少见但实用的语句ALTER TABLE tb_emp DROP FOREIGN KEY emp_dept; SHOW CREATE TABLE tb_emp \G;DROP FOREIGN KEY 后面跟的是外键约束名也就是建表时 CONSTRAINT 关键字后面的名字不是字段名。如果建表时没显式指定约束名MySQL 会自动生成查 SHOW CREATE TABLE 的输出能看到。\G 表示把查询结果按纵向列显示字段多的时候比默认表格更易读这在命令行运维时是个很顺手的小技巧。执行顺序上的经验是先 ALTER 把表结构调整到位再 INSERT 数据最后 SELECT 验证。ALTER 改字段名或类型时已有数据会按新结构重新解释如果先插数据再改字段虽然 MySQL 会保留数据但字段名变更后你原来 INSERT 语句里的字段引用就可能对不上了。这个顺序原则在后续多个关卡里都适用。4. 查询语法全梳理从单表查询到子查询与存储过程4.1 单表查询WHERE、LIKE、IN、BETWEEN 的组合使用单表查询的前两个关卡特地把最常用的过滤关键字分成小关。先看基础查询和 INselect Name,Salary from tb_emp; select * from tb_emp; SELECT Name,Salary FROM tb_emp WHERE Id NOT IN (1);select * 查全表实训环境数据量小没压力生产库上不推荐因为会多传不需要的列。IN 的作用是字段值匹配括号内任一值就命中NOT IN 正好相反。IN 后面还能接子查询WHERE id IN (SELECT id FROM ...)这是后面复杂查询频繁用到的能力这里先记住写法。范围查询和模糊查询SELECT Name,Salary FROM tb_emp WHERE Salary BETWEEN 3000 AND 5000; SELECT Name,Salary FROM tb_emp WHERE Name LIKE C%;BETWEEN 3000 AND 5000 是闭区间包含 3000 和 5000 本身等价于 Salary3000 AND Salary5000。LIKE C% 匹配以 C 开头的名字% 是任意长度通配符_ 是单个字符通配符。如果题目要求匹配姓名第二个字符是 a 的人写法是 LIKE _a%注意中英文通配符在使用上没有差别但字符集必须统一。空值查询与去重SELECT * FROM tb_emp WHERE DeptId IS NULL; SELECT DISTINCT Name FROM tb_emp;判断空值必须用 IS NULL不能写成 NULLNULL 在 SQL 里不等于任何值包括它自己。DISTINCT 是对查询结果去重它作用于 SELECT 后面所有列的组合SELECT DISTINCT Name 只对 Name 去重如果写成 SELECT DISTINCT Name,DeptId只有 Name 和 DeptId 组合完全相同时才会去重。多条件查询和排序SELECT * FROM tb_emp WHERE DeptId301 AND Salary 3000; SELECT * FROM tb_emp WHERE DeptId301 OR DeptId303; select * from tb_score where class_id 1 order by score desc;AND 的优先级高于 OR混合使用时最好加括号比如 WHERE (DeptId301 OR DeptId303) AND Salary3000否则语义会变成301 部门的全部记录加上 303 部门里工资大于 3000 的记录结果集和预期完全不同。ORDER BY score desc 是降序asc 是升序且是默认排序方向多字段排序用逗号分隔比如 ORDER BY class_id, score desc先按班级排同班级内再按分数降序。4.2 分组、分页与连接查询从 GROUP BY 到 JOIN分组查询和分页SELECT * FROM tb_class GROUP BY class_id; SELECT * FROM tb_score order by score desc LIMIT 1,4;GROUP BY 对 class_id 分组后SELECT * 在 MySQL 关闭 only_full_group_by 模式时能返回每组第一行但严格模式下会直接报错。实训环境如果报错改成 SELECT class_id, COUNT(*) FROM tb_class GROUP BY class_id 这类聚合写法即可。LIMIT 1,4 的意思是跳过第 1 行取 4 行也就是返回第 2 到第 5 名MySQL 8.0.17 之后的写法是 LIMIT 4 OFFSET 1两个参数的位置反过来了很多头歌实训镜像还在用 MySQL 5.7旧写法兼容性更好你本地如果是 8.0两种写法都认一下做题时先看清环境。内连接查询select tb_student.name as studentName, tb_class.name as className from tb_student join tb_class on tb_class.id tb_student.class_id;INNER JOIN 只返回两表都匹配上的行on 后面是连接条件。as 是别名studentName 和 className 是结果集的列名头歌评测对列名的要求很严格题目要求别名写成 studentName你写成 student_name 就会判输出不一致。外连接查询select tb_student.name as studentName, tb_class.name as className from tb_class right join tb_student on tb_class.id tb_student.class_id; select tb_student.name as studentName, tb_class.name as className from tb_class left join tb_student on tb_class.id tb_student.class_id;left join 保留左表全部行右表没有匹配的补 NULLright join 保留右表全部行正好相反。这里有个容易混淆的点第2关题面说的是使用左外连接查询所有学生姓名和对应的班级但答案给的是 right join因为主表 tb_student 在右侧RIGHT JOIN tb_student 等价于把 LEFT JOIN 的表位置调换语义上都是保留学生的全部记录。做题时先确认哪张表是全保留的全保留的表在 LEFT JOIN 时放左边在 RIGHT JOIN 时放右边就不会写反。4.3 子查询与复杂查询把标答思路拆出来讲子查询关卡的答案很有代表性-- 查询大于所有平均年龄的员工姓名与年龄 select name, age from tb_emp where age (select avg(age) from tb_emp); -- 使用 ALL/ANY/IN 关键字进行查询 SELECT position, salary FROM tb_salary WHERE salary ANY(SELECT max(salary) FROM tb_salary where positionjava); SELECT position, salary FROM tb_salary WHERE salary ANY(SELECT min(salary) from tb_salary where positionjava); select position, salary from tb_salary where position in(java);WHERE age (SELECT AVG(age) ...) 是把子查询结果当作单个值使用这种标量子查询要求子查询只返回一行一列。ANY 和 ALL 的区别在于salary ANY(子查询) 表示大于子查询结果中的任意一个值也就是大于最小值salary ALL(子查询) 表示大于子查询结果中的全部值也就是大于最大值。资源里 ALL 的写法其实有个小问题——SELECT max(salary) 只返回一个最大值再拿 salary 跟它比ALL 和 ANY 在这个场景下语义几乎一样真正能看出区别的用例是对多行结果集比较做题时不用在这里较真知道概念就行。复杂查询里有几道经典题比如体育馆的人流量select distinct a.* from gymnasium a, gymnasium b, gymnasium c where a.visitors_flow100 and b.visitors_flow100 and c.visitors_flow100 and ( (a.id b.id-1 and b.id c.id - 1) or (a.id b.id-1 and a.id c.id 1) or (a.id b.id1 and b.id c.id 1) ) order by a.id;这是一种自连接写法把同一张表复制成三个实例 a、b、c通过 id 的相邻关系找出连续三天人流量都大于等于 100 的记录。思路是先把过滤条件压到 WHERE再用 id 差 1 建立相邻关系。这种三表自连接的可读性很差但它是题目的标答读题时抓住连续三天这个关键词就能联想到这种解法。分数排名那道题用了相关子查询select Score, (select count(distinct score) from score where score s.score) as Rank from score as s order by Score desc;外层每一行都执行一次内层子查询统计有多少个不同的分数大于等于当前行分数结果是几就是第几名。这是手写排名的经典解法比 MySQL 8.0 的 RANK() 窗口函数要麻烦但环境如果是 5.7 也只能这么写。注意 count(distinct score) 里的 distinct 不能省否则并列分数会重复计数排名就错了。4.4 聚合函数与其他内置函数COUNT/SUM/AVG/MAX/MIN 的固定搭配聚合函数这一章题面非常套路select count(*) from tb_class; select classid, count(*) from tb_class where classid367; select sum(score) from tb_class; select course, sum(score) from tb_class where course语文; select course, avg(score) from tb_class where course语文; select course, max(score) from tb_class where course语文; select course, min(score) from tb_class where course英语;COUNT() 统计行数COUNT(某列) 统计该列非空值的个数两者在列存在 NULL 时结果会不一样。AVG 只对数值列有效遇到 NULL 会跳过而不是当 0 算。MAX/MIN 对字符串列也适用按字典序取最大最小。组合使用时记住一个总原则WHERE 在分组前过滤数据HAVING 在分组后过滤组GROUP BY 后面的聚合条件只能写在 HAVING 里。这个原则在分组选择数据关卡里反复出现比如查询至少两门课在 90 分以上的学生COUNT() 的过滤条件就要写在 HAVING 而不是 WHERE。字符函数、数学函数和自定义函数这一章最有价值的是自定义函数这一段delimiter // create function fn_three_max(param_1 int, param_2 int, param_3 int) RETURNS int BEGIN DECLARE max_val int DEFAULT 0; if param_1 param_2 then set max_val param_1; else set max_val param_2; end if; if param_3 max_val then set max_val param_3; end if; return max_val; END//delimiter // 的作用是把语句结束符临时改成 //因为函数体内 BEGIN...END 块包含多个分号如果还用默认的 ; 结尾MySQL 会在第一个分号处就认为语句结束然后报错。DECLARE 声明局部变量并赋初值if/else 结构控制逻辑最后 RETURN 返回结果。函数和存储过程的区别在于函数必须返回一个值且只能返回一个值存储过程用 OUT 参数返回多个值用 CALL 调用。视图那关的代码是 CREATE VIEW stu_view AS select math, chinese, mathchinese FROM student视图相当于一张虚拟表不存储数据查询时实时计算。索引关卡里 CREATE UNIQUE INDEX 是唯一索引CREATE INDEX 创建普通索引ALTER TABLE ... ADD INDEX name_city_score(name, age, address) 是组合索引三个字段的顺序决定了索引匹配的最左前缀规则。5. 头歌MySQL实训常见问题与避坑排查记录5.1 登录失败-p 与 -h 的典型翻车现场现象输入 mysql -uroot -p123123 -h127.0.0.1 后报 Access denied for user root。原因实训容器里数据库的密码不是 123123或者端口被映射过默认 3306 连不上还有一种常见情况是把 -p 和密码写成了 -p 123123中间多了空格MySQL 会把 123123 当成需要交互输入的密码提示符导致认证失败。解决先执行 mysql -uroot -p 回车后手动输入密码。如果还不行检查实训平台给出的数据库连接信息把 -h 改成平台指定的内网地址并补上 -P 端口参数。我一般会在第一关先跑一条 select version(); 验证连接是否真的成功再往下做。5.2 评测只认 BEGIN END 之间的内容多写一句话可能整关判错现象代码在本地 SQL 工具里跑通了但头歌评测就是不通过。原因头歌的实训关卡通常用 BEGIN 和 END 注释把代码块框起来评测脚本只比对这部分内容。如果答案区外面还留着 use MyDb; 或 show tables;或者把两条不相干的 SQL 塞进同一个 BEGIN END都会干扰评测。解决严格按题目给的代码块结构填写一个 BEGIN...END 里只放这一关要求的语句。比如单表查询二第2关有两个 BEGIN END 块第一块放 SELECT * FROM tb_emp WHERE DeptId IS NULL;第二块放 SELECT DISTINCT Name FROM tb_emp;位置和顺序都不能乱。我自己的习惯是先把自己答案里的注释全删掉再逐块提交注释留在评测代码段里有时也会引发问题。5.3 外键建不上类型不一致和字段没索引是两大元凶现象执行建表语句报 ERROR 1215 (HY000): Cannot add foreign key constraint。原因子表外键字段类型和父表主键字段类型不一致比如父表 id 是 INT子表 classId 是 VARCHAR或者父表被引用的字段不是主键也没有索引。解决先 DROP TABLE 相应表重来仔细对齐两边的类型和长度。父表引用字段必须是 PRIMARY KEY 或有索引t_class 表里 id 已经是主键所以没问题但如果自己模仿题目写别的表最容易栽在这里。另外两张表的存储引擎都要是 InnoDBMyISAM 不支持外键约束如果你建表时手动指定过 ENGINEMyISAM外键一样建不上。5.4 LIMIT 的偏移量经常理解反现象查询第 2 名到第 5 名学生运行结果却少了第一行或者范围不对。原因LIMIT 1,4 的语义是跳过 1 条取 4 条不是从第 1 条开始取 4 条。题目说第 2 名到第 5 名应该跳过第 1 名取 4 条所以 LIMIT 1,4 是对的。新手容易写成 LIMIT 2,5那就是从第 3 名开始取 5 条结果完全错位。解决做题前先在心里换算要第 M 到第 N 条LIMIT 后面第一个参数是 M-1第二个参数是 N-M1。本地验证时先跑一次不带 LIMIT 的排序结果人工数一下偏移量对不对再套上 LIMIT。5.5 大小写、字符集和 delimiter 的隐蔽问题现象界面出现乱码或自定义函数提交后报语法错误。原因字符集没指定 utf8中文数据存进去再查出来就是乱码Linux 下库表名区分大小写MyDb 和 mydb 被当成两个对象自定义函数没写 delimiter //函数体里的分号导致语句被提前截断。解决建表时统一加 DEFAULT CHARSETutf8连接时也可以追加 --default-character-setutf8。函数和存储过程前面固定先写 delimiter //结束后写 delimiter ; 恢复这个习惯不能省。判断大小写问题用 SHOW TABLES; 看实际存在的表名再对照你的 use 语句里大小写是否一致。6. 提交前的自检习惯用三句SQL把每一关锁死头歌的评测场景里最气人的不是你不会写 SQL而是你写得对但输出有偏差。我自己后来养成了一个固定流程每做完一关先不急着提交按下面三步自查第一步用 DESCRIBE 表名; 确认表结构。建表关卡特容易在字段类型、默认值、约束上少写一个逗号或多写一个括号DESCRIBE 会把字段名、类型、是否为空、键信息、默认值全部列出来和你心里的预期结构逐行比对。第二步用 SHOW CREATE TABLE 表名\G; 看建表语句的完整原文。这一句在删除外键、修改表名这类关卡里特别管用它能直接看到当前表的外键约束名叫什么、字符集是什么、自增列还在不在。第三步用 SELECT 带条件回查数据。UPDATE 和 DELETE 做完之后一定跑一遍 SELECT 确认影响的行数是不是题目要求的范围比如改 id3 那条就 SELECT * FROM tb_emp WHERE id3;看到结果已经是新的 Name 和 Salary 再提交。这三个动作加在一起不会超过两分钟但能规避掉绝大多数因为大小写、别名、字段顺序导致的输出不一致。资源里视图和索引两关的答案出现了雷同的代码那多半是整理时的复制笔误真正做题时一个关卡特招 CREATE VIEW另一个卡特招 CREATE INDEX别照抄。从那以后我每次在头歌上刷 MySQL 实训都强制自己按DESCRIBE → SHOW CREATE TABLE → SELECT 回查走一遍顺序执行完再点提交通过率明显比直接跑一遍答案高。遇到不会的题先卡在哪个关键词上再用这份 PDF 对照着查对应关卡比自己瞎改命令高效得多。希望帮到你。本文还有配套的精品资源点击获取