MySQL · 错误码速查
MySQL 错误 1215:无法添加外键约束——在 8.4 里先确认真的是 1215,再按 3 种剩余情况查
ERROR 1215 (HY000): Cannot add foreign key constraint 不告诉你原因。在 MySQL 8.4.7 测试库里,类型/有无符号/字符集/排序规则不一致改报 3780,父列没有唯一键报 6125,父表不存在或是 MyISAM 报 1824;还报 1215 的只有 3 种:临时表带外键、存储生成列的基列上 ON UPDATE CASCADE、FOREIGN_KEY_CHECKS=0 时先建了子表,之后建的父表列类型对不上。如果你看到 1215 但不是这三种,先确认服务器版本——你看的很可能是旧版本或旧教程的排查清单。
官方原文
Cannot add foreign key constraint官方错误参考:Error number 1215;Symbol ER_CANNOT_ADD_FOREIGN;SQLSTATE HY000。同一参考里另有 3780 ER_FK_INCOMPATIBLE_COLUMNS、6125 ER_FK_NO_UNIQUE_INDEX_PARENT、1822 ER_FK_NO_INDEX_PARENT、1824 ER_FK_CANNOT_OPEN_PARENT 等更具体的外键错误。
出处:MySQL 8.4 Error Reference:Server Error Message Reference 最后核对:
| 错误号 / 符号 | 1215 / ER_CANNOT_ADD_FOREIGN | 出处 |
|---|---|---|
| SQLSTATE | HY000 | 出处 |
| 8.4.7 测试库 20 种外键失败 | 3 种报 1215,其余为 3780 / 6125 / 1822 / 1824 / 1830 / 1506 / 3733 / 1553 / 1452 / 1170 | |
| restrict_fk_on_non_standard_key | 8.4 默认 ON:引用非唯一键 / 部分键的外键直接报 6125 | 出处 |
| SHOW WARNINGS | 对 1215 不提供额外原因,只重复 Error 1215 | |
| 最后核对 | 2026-11-11 |
盈尺实测(测试库,非官方文档):MySQL 8.4.7 测试库自造表,20 种外键失败的报错码、1 种静默丢外键、100 万行子表加外键耗时。 看 1215 实战长文:20 种外键失败逐条对照 →
8.4 里还报 1215 的 3 种情况(测试库实测)
2026-11-11 在 box 本机测试库(MySQL 8.4.7,默认 sql_mode,utf8mb4,表和数据全部自造,非客户环境)逐条执行,只有下面 3 句返回 ERROR 1215 (HY000): Cannot add foreign key constraint:
| 情况 | 触发语句(节选) | 官方依据 |
|---|---|---|
| 临时表带外键 | CREATE TEMPORARY TABLE d7(… FOREIGN KEY(pid) REFERENCES parent(id)) | 父子表都不能是临时表 |
| 存储生成列的基列上 ON UPDATE CASCADE | x INT, g INT AS (x) STORED, FOREIGN KEY(x) REFERENCES parent(id) ON UPDATE CASCADE | 存储生成列的基列外键不能用 CASCADE / SET NULL / SET DEFAULT 作为 ON UPDATE 动作 |
| FOREIGN_KEY_CHECKS=0 先建子表,之后建父表类型不符 | 子表 pid INT 引用尚不存在的 later_parent;checks=1 后 CREATE TABLE later_parent(id BIGINT PRIMARY KEY) | 报错发生在建父表那一句 |
第三种最反直觉:你执行的是一条普通的 CREATE TABLE,里面没有任何外键语法,也会报 1215。原因是之前在 FOREIGN_KEY_CHECKS=0 下建的子表已经声明了引用它,父表一出现就被校验。常见于按依赖顺序以外的顺序导入 dump、或迁移脚本里先关外键检查再建表。
同样是「外键加不上」,8.4 实际报的码
| 原因 | 8.4.7 测试库报错 |
|---|---|
| INT 引用 INT UNSIGNED / BIGINT 引用 INT / 字符集或排序规则不同 | 3780 Referencing column … and referenced column … are incompatible. |
| ALTER TABLE 加外键时类型不符、改父列类型 | 3780 |
| 父列无索引或只有非唯一索引(默认 restrict_fk_on_non_standard_key=ON) | 6125 Failed to add the foreign key constraint. Missing unique key … |
| 同上但 restrict 关掉:无索引 / 非唯一索引 | 1822 Missing index … / 可建成但 Warning 6124(已弃用) |
| 父表不存在、父表是 MyISAM | 1824 Failed to open the referenced table … |
| ON DELETE SET NULL 但子列 NOT NULL | 1830 Column … cannot be NOT NULL |
| 父表分区 | 1506 Foreign keys are not yet supported in conjunction with partitioning |
| 虚拟生成列做外键 | 3733 … uses virtual column … which is not supported. |
| 子表已有孤儿数据再加外键 | 1452 Cannot add or update a child row |
所以照着「1215 先查类型、字符集、索引」的老清单排查,在 8.4 上你根本不会看到 1215,而是这些更具体的码。告警规则和迁移脚本的错误处理如果只捕获 1215,会漏掉 3780 / 6125。孤儿数据的处理见 1452 速查页。
更该担心的不是报错:MyISAM 子表和 FOREIGN_KEY_CHECKS=0 会静默放过
- MyISAM 子表写外键不报错:测试库
CREATE TABLE c8(… FOREIGN KEY(pid) REFERENCES parent(id)) ENGINE=MyISAM执行成功,SHOW CREATE TABLE c8里只剩KEY pid,外键被丢掉了。官方要求父子表使用同一存储引擎。 - FOREIGN_KEY_CHECKS=0 引用不存在的父表:建表成功、无警告,直到父表出现才校验(见上一段第三种)。
- FOREIGN_KEY_CHECKS=0 下给已有孤儿数据的表加外键:100 万行子表加 1 行孤儿,checks=0 时 ALTER 成功,之后 LEFT JOIN 仍查出 1 行孤儿;checks=1 时同一操作约 5.4 秒后报 1452。
SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND ENGINE <> 'InnoDB';
SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE();报了 1215 怎么拿到具体原因
SELECT VERSION();确认版本。8.4 上类型、索引类问题不会报 1215。SHOW WARNINGS在测试库里只重复Error 1215 Cannot add foreign key constraint,没有额外信息。SHOW ENGINE INNODB STATUS\G看LATEST FOREIGN KEY ERROR:第三种情况(checks=0 后建父表)测试库里写着Error in foreign key constraint of table labdb/x10: there is no index in referenced table which would contain the columns as the first columns, or the data types in the referenced table do not match the ones in table,直接点名了是哪张子表。临时表和存储生成列两种在 SQL 层就被拒,这一段不会更新。- 对照 3 种剩余情况:语句里有没有
TEMPORARY、外键列是不是某个 STORED 生成列的基列、之前是否在 checks=0 下建过引用它的子表。
常见问题
mysql 1215 无法添加外键约束是什么原因?
1215 是笼统的外键创建失败。在 MySQL 8.4.7 测试库里只剩 3 种情况还报 1215:临时表带外键、存储生成列的基列上用 ON UPDATE CASCADE、FOREIGN_KEY_CHECKS=0 先建子表后父表列类型不符。类型、字符集、索引问题在 8.4 改报 3780、6125、1822。
字段类型不一致为什么报 3780 而不是 1215?
8.4 用 3780(ER_FK_INCOMPATIBLE_COLUMNS)专门报引用列与被引用列不兼容,包括有无符号、INT/BIGINT、字符集和排序规则不同。VARCHAR 长度不同但字符集排序规则相同可以建成功。
SHOW WARNINGS 看不到 1215 的原因怎么办?
看 SHOW ENGINE INNODB STATUS 的 LATEST FOREIGN KEY ERROR 段。临时表、存储生成列两种在 SQL 层被拒,不会写入这一段,需要对照语句本身判断。
建表时没写外键也报 1215?
检查是否有其他表在 FOREIGN_KEY_CHECKS=0 时声明了引用这张表、且列类型对不上。父表创建时会被校验,报错落在 CREATE 父表那一句。
MyISAM 表能建外键吗?
不能。测试库里 MyISAM 子表写外键语法不报错,但外键被静默丢弃;父表是 MyISAM 时报 1824。
下一步
价格以对应页面当前标价为准。
出处(最后核对 2026-11-11)
- MySQL 8.4 Error Reference:Server Error Message Reference
- MySQL 8.4 Reference Manual:FOREIGN KEY Constraints
- MySQL 8.4 Reference Manual:Server System Variables(restrict_fk_on_non_standard_key)
本页摘录并解读上面列出的官方文档,不是官方页面;官方文档更新后以官方为准。除标明「盈尺实测」的一段外,其余内容都来自官方文档。