跳到主要内容

附录 A:常见错误与解决方案

新手学 MySQL,一半时间在写 SQL,另一半时间在和报错搏斗。这份速查手册收录了新手最高频的十几个报错,遇到问题直接 Ctrl+F 搜错误码即可。

遇到报错的通用排查思路

别慌,报错不是事故,是 MySQL 在用固定格式跟你说话。按下面四步走,绝大多数问题 5 分钟内能解决:

  1. 看错误码:每个错误都有编号,如 ERROR 1064。错误码是精确的"病名",比模糊描述有用得多。
  2. 读英文关键信息:错误信息里的英文往往直接点明了问题,抓关键词就行——Access denied(拒绝访问)、Unknown column(不认识的列)、Duplicate entry(重复的值)。看不懂整句没关系,认出关键词就够了。
  3. 检查拼写和标点:新手错误的重灾区——中文标点("")、表名列名拼错、少写逗号、引号没配对。把出错的那行逐字符看一遍。
  4. 搜索:把「错误码 + 关键英文」原样丢给搜索引擎,如 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 mysqlbrew 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 系统上库名区分大小写Schoolschool 是两个库。

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 语法错误,新手第一大高频错。四大常见诱因:

  1. 中文标点:中文逗号 、中文引号 ""、中文括号 ()——切换输入法时最容易混进来,肉眼还很难发现。
  2. 关键字拼错SELECT 写成 SELCETFROM 写成 FORMWHERE 写成 WHER
  3. 少逗号 / 多逗号:列名之间漏了逗号,或最后一列后面多写了逗号。
  4. 用保留字做表名/列名:比如把列叫 orderdescgroup,撞上了 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)超出了这一列字符集的表达能力。典型场景:表是老旧的 latin1utf8(MySQL 的 utf8 是残血版,最多 3 字节,存不了 emoji),你却往里存中文或 emoji。

解决办法

  • 建库建表统一用 utf8mb4CREATE 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 走天下,建库时就设好,成本最低。