附录 A:常见错误与解决方案
新手学 MySQL,一半时间在写 SQL,另一半时间在和报错搏斗。这份速查手册收录了新手最高频的十几个报错,遇到问题直接 Ctrl+F 搜错误码即可。
遇到报错的通用排查思路
别慌,报错不是事故,是 MySQL 在用固定格式跟你说话。按下面四步走,绝大多数问题 5 分钟内能解决:
- 看错误码:每个错误都有编号,如
ERROR 1064。错误码是精确的"病名",比模糊描述有用得多。 - 读英文关键信息:错误信息里的英文往往直接点明了问题,抓关键词就行——
Access denied(拒绝访问)、Unknown column(不认识的列)、Duplicate entry(重复的值)。看不懂整句没关系,认出关键词就够了。 - 检查拼写和标点:新手错误的重灾区——中文标点(
,、"")、表名列名拼错、少写逗号、引号没配对。把出错的那行逐字符看一遍。 - 搜索:把「错误码 + 关键英文」原样丢给搜索引擎,如
MySQL ERROR 1452 foreign key constraint fails,你踩的坑,前人一定踩过。
1. ERROR 1045 (28000): Access denied for user
错误信息
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
原因:用户名或密码错了。也可能是密码对了但该用户不允许从当前主机登录('root'@'localhost' 中 @ 后面就是允许的来源主机)。
解决办法
- 确认密码大小写、有没有多敲空格;注意
-p后直接回车再输密码,别把密码明文跟在-p后面时多打了空格(-p 123456是错的,要么-p123456紧挨着,要么只写-p)。 - 确认用户名:
mysql -u root -p,-u后是不是拼对了。 - 密码彻底忘了?见本页第 13 条「忘记 root 密码」。
2. ERROR 2003 (HY000): Can't connect to MySQL server
错误信息
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost:3306' (10061)
原因:客户端根本没连上服务器——大概率是 MySQL 服务没启动,其次是端口号/主机地址写错,或被防火墙拦了。
解决办法
- Windows:管理员身份打开命令行,
net start mysql(服务名可能是mysql80,可在"服务"面板里确认)。 - Linux/Mac:
sudo systemctl start mysql或brew services start mysql。 - 检查端口:默认 3306,若安装时改过,连接时要加
-P 端口号(大写 P)。 - 连远程服务器连不上,检查服务器防火墙和云服务器安全组是否放行 3306。
3. ERROR 1049 (42000): Unknown database
错误信息
ERROR 1049 (42000): Unknown database 'schol'
原因:要用的数据库不存在。要么名字拼错(如上例把 school 拼成了 schol),要么真的还没建。
解决办法
SHOW DATABASES;看看到底有哪些库,核对名字。- 确实没建就先
CREATE DATABASE school;。 - 注意 Linux 系统上库名区分大小写,
School和school是两个库。
4. ERROR 1146 (42S02): Table doesn't exist
错误信息
ERROR 1146 (42S02): Table 'school.students' doesn't exist
原因:表不存在。常见三种情况:表名拼错(student 写成 students)、忘了先 USE 选库(在别的库里找表)、表还没建。
解决办法
SHOW TABLES;核对当前库里的表名,注意单复数。- 用
SELECT DATABASE();确认自己在哪个库,必要时USE school;。 - 也可以用
库名.表名的全名写法:SELECT * FROM school.student;。
5. ERROR 1064 (42000): SQL syntax error
错误信息
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual ...
for the right syntax to use near 'xxx' at line 1
原因:SQL 语法错误,新手第一大高频错。四大常见诱因:
- 中文标点:中文逗号
,、中文引号""、中文括号()——切换输入法时最容易混进来,肉眼还很难发现。 - 关键字拼错:
SELECT写成SELCET、FROM写成FORM、WHERE写成WHER。 - 少逗号 / 多逗号:列名之间漏了逗号,或最后一列后面多写了逗号。
- 用保留字做表名/列名:比如把列叫
order、desc、group,撞上了 MySQL 的保留字。
解决办法
- 重点看提示中
near 'xxx'的部分:错误就在 xxx 处或它的前一个词附近。 - 把整条 SQL 切到英文输入法重新敲一遍标点。
- 保留字做名字时用反引号包起来:
`order`,或干脆改名(如order_id)。
6. ERROR 1062 (23000): Duplicate entry
错误信息
ERROR 1062 (23000): Duplicate entry '1' for key 'student.PRIMARY'
原因:插入或修改的值撞上了主键或唯一约束——比如主键 id=1 已经有人了,或违反了 UNIQUE(student_id, course_id)(同一学生同一门课重复录成绩)。
解决办法
- 先查一下冲突的值是否已存在:
SELECT * FROM student WHERE id = 1;。 - 主键是自增列的话,插入时干脆不指定 id,让 MySQL 自己分配。
- 若本意是"有则更新、无则插入",可用
INSERT ... ON DUPLICATE KEY UPDATE ...或REPLACE INTO。
7. ERROR 1452 (23000): 外键约束失败(插入/更新)
错误信息
ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails (`school`.`score`, CONSTRAINT `fk_score_student`
FOREIGN KEY (`student_id`) REFERENCES `student` (`id`))
原因:往子表插的外键值,在父表里找不到。比如给 student_id = 99 录成绩,但 student 表根本没有 99 号学生。外键约束就是防止这种"幽灵数据"的。
解决办法
- 先确认父表有没有这条记录:
SELECT * FROM student WHERE id = 99;。 - 顺序要对:先插父表(学生),再插子表(成绩)。
- 检查是不是外键值手滑写错了。
8. ERROR 1451 (23000): 被外键引用,无法删除
错误信息
ERROR 1451 (23000): Cannot delete or update a parent row:
a foreign key constraint fails ...
原因:和 1452 是一对"镜像"错误:你想删父表的记录(如删除一名学生),但子表里还有引用它的行(他的成绩还在)。直接删会产生孤儿数据,MySQL 拒绝。
解决办法
- 正确顺序:先删子表相关行,再删父表:先
DELETE FROM score WHERE student_id = 1;再删学生。 - 若希望"删学生自动删他的成绩",建表时可给外键加
ON DELETE CASCADE(级联删除,用之前想清楚后果)。
9. ERROR 1366 (HY000): Incorrect string value(字符集问题)
错误信息
ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89...' for column 'name' at row 1
原因:想存的字符(中文、emoji)超出了这一列字符集的表达能力。典型场景:表是老旧的 latin1 或 utf8(MySQL 的 utf8 是残血版,最多 3 字节,存不了 emoji),你却往里存中文或 emoji。
解决办法
- 建库建表统一用
utf8mb4:CREATE DATABASE school DEFAULT CHARACTER SET utf8mb4;。 - 已有的表可以改:
ALTER TABLE student CONVERT TO CHARACTER SET utf8mb4;。 - 用
SHOW CREATE TABLE student;可查看表当前的字符集。
10. ERROR 1054 (42S22): Unknown column
错误信息
ERROR 1054 (42S22): Unknown column 'nmae' in 'field list'
原因:列名不存在。要么拼错了(name 敲成 nmae),要么这个列在别的表里,要么字符串忘了加引号——WHERE name = 张三 会让 MySQL 把 张三 当成列名去找,找不到就报 1054。
解决办法
DESC student;查看表结构,核对列名。- 字符串值一定要加引号:
WHERE name = '张三'。 - 多表连接时给列加上表前缀,如
student.name,避免歧义。
11. ERROR 1175: Safe update mode(安全更新模式)
错误信息
ERROR 1175: You are using safe update mode and you tried to update a table
without a WHERE that uses a KEY column.
原因:MySQL Workbench 等工具默认开启"安全更新模式",禁止不带(基于索引列的)WHERE 条件的 UPDATE/DELETE——这是在保护你,防止一条语句误伤全表。
解决办法
- 首选:老老实实在 WHERE 里用主键或索引列,如
UPDATE student SET gender='女' WHERE id = 3;。 - 确实要全表更新,可临时关闭:
SET SQL_SAFE_UPDATES = 0;,做完建议再SET SQL_SAFE_UPDATES = 1;打开。
12. 中文乱码问题排查
现象:查询结果里中文显示为 ??? 或 å¼ ä¸‰ 一类的乱码,但不一定报错。
原因:从客户端 → 连接 → 服务器 → 表 → 列,这条链路上任何一环字符集不一致都会乱码。就像两个人打电话,一个说中文一个按英文理解,内容全变成噪音。
解决办法(按顺序检查)
-- 1. 查看各环节字符集
SHOW VARIABLES LIKE 'character%';
-- 2. 查看表的字符集
SHOW CREATE TABLE student;
- 保证三处统一为
utf8mb4:连接字符集(客户端执行SET NAMES utf8mb4;)、库、表。 - Windows 的 cmd 窗口默认 GBK 编码,若只是命令行里显示乱、程序里读取正常,可尝试
chcp 65001把窗口切到 UTF-8。 - 注意:已经以错误编码存进去的乱码数据,改字符集救不回来,需要重新导入。
13. 忘记 root 密码怎么办
现象:密码彻底想不起来,1045 反复拒绝。
解决办法(以 MySQL 8.0 / Windows 为例,Linux 思路相同):
# 1. 停止 MySQL 服务(管理员命令行)
net stop mysql80
# 2. 以"跳过权限验证"方式启动(此窗口会被占用,保持别关)
mysqld --console --skip-grant-tables --shared-memory
# 3. 另开一个命令行,无密码登录
mysql -u root
-- 4. 先刷新权限表,再改密码
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
# 5. 关掉第 2 步的窗口,正常重启服务,用新密码登录
net start mysql80
⚠️
--skip-grant-tables状态下任何人都能免密登录,改完密码务必立刻恢复正常启动。
14. ERROR 1142 (42000): 权限不足
错误信息
ERROR 1142 (42000): UPDATE command denied to user 'teacher'@'localhost' for table 'score'
原因:当前登录的用户没有执行该操作的权限。比如实战篇里我们给 teacher 账号只授了视图的 SELECT 权限,它去 UPDATE 底层表自然被拒。
解决办法
SHOW GRANTS;查看当前用户拥有哪些权限,先搞清楚"我是谁、我能干什么"。- 确实需要权限,找管理员(root)授权:
GRANT UPDATE ON school.score TO 'teacher'@'localhost';。 - 学习环境图省事可直接用 root 操作;但生产环境请坚持最小权限原则——报 1142 往往说明权限设计正在起作用,先想想"这个账号本来就不该有这个权限吧?"
📝 小结
- 报错四步走:看错误码 → 抓英文关键词 → 查拼写标点 → 搜索。
- 连接类(1045/2003)查密码和服务;对象不存在类(1049/1146/1054)查名字拼写和当前库;语法类(1064)查中文标点、关键字、逗号、保留字。
- 约束类报错(1062/1452/1451)不是麻烦,是约束在替你挡脏数据;权限类(1142/1175)是安全机制在替你挡误操作。
- 字符集问题一律
utf8mb4走天下,建库时就设好,成本最低。