errno 150 最常见原因是外键与主键字段类型不严格一致,包括数据类型、长度、符号性(如 UNSIGNED);其次需确保被引用列为主键或唯一索引、引擎为 InnoDB、字符集与排序规则统一,且建表顺序正确、外键名不冲突。

检查外键字段与主键字段的类型是否完全一致
errno 150 最常见的根源是类型“看似相同实则不匹配”。MySQL 要求外键列和被引用的主键列在 数据类型、长度、符号性(SIGNED/UNSIGNED) 上必须严格一致,差一个括号里的数字都不行。
比如主键是 INT(10) UNSIGNED,外键写成 INT(11) UNSIGNED 或 INT(10)(缺 UNSIGNED)都会失败。别信 GUI 工具显示的“int”,得用命令确认:
SHOW COLUMNS FROM `parent_table` LIKE 'id';
SHOW COLUMNS FROM `child_table` LIKE 'parent_id';
- 对比
Type列的完整输出,包括括号内数字和unsigned标记 -
TINYINT和SMALLINT不兼容,哪怕都存数字 -
VARCHAR必须长度一致,VARCHAR(50)引用VARCHAR(64)会报错 - 枚举或 set 类型无法做外键,直接换
ENUM到VARCHAR再建索引
确认被引用列是否为主键且已建索引
外键只能引用 PRIMARY KEY 或带 UNIQUE 约束的索引列。如果被引用列只是普通字段、或虽有索引但不是唯一索引,也会触发 errno 150。
执行这条语句查目标列是否满足条件:
SHOW INDEX FROM `parent_table` WHERE Column_name = 'id';
- 看
Key_name是否为PRIMARY,或Non_unique = 0(表示唯一索引) - 如果没结果,说明没索引——需先加:
ALTER TABLE `parent_table` ADD PRIMARY KEY (id);或ADD UNIQUE INDEX idx_id (id); - 注意:MyISAM 表即使加了索引也不支持外键,引擎必须是
InnoDB
验证字符集、排序规则与存储引擎是否统一
三个层面必须对齐:表级字符集、列级 collation、引擎类型。任一不一致,外键就会被拒绝。
查法如下:
SHOW CREATE TABLE `parent_table`;
SHOW CREATE TABLE `child_table`;
- 比对两表的
ENGINE=InnoDB是否都存在;DEFAULT CHARSET=utf8mb4和COLLATE=utf8mb4_0900_ai_ci是否完全一致 - 如果被引用列定义时指定了 collation(如
CHARACTER SET latin1 COLLATE latin1_swedish_ci),外键列也必须显式声明相同值 - 常见坑:用 phpMyAdmin 导入时默认用
utf8,而新 MySQL 默认是utf8mb4,导致隐式不匹配
排查外键名称冲突与建表顺序问题
MySQL 要求被引用的表必须**先存在**,且外键名在当前库中不能重复。这两点容易在批量建表或迁移脚本里翻车。
- 建表 SQL 中若含
FOREIGN KEY `fk_name`,先执行SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = 'your_db' AND CONSTRAINT_NAME = 'fk_name';确认未重名 - 脚本里如果
CREATE TABLE child在CREATE TABLE parent之前,必然失败——调整顺序,或改用ALTER TABLE child ADD FOREIGN KEY ...分步操作 - 已有同名外键残留?删掉再试:
ALTER TABLE child DROP FOREIGN KEY fk_name;(注意:这里fk_name是约束名,不是列名)
真正卡住的时候,往往不是单一原因。建议按「类型→索引→引擎/字符集→顺序/命名」这个顺序逐项验证,比盲目改语法更省时间。尤其注意 SHOW 命令返回的真实定义,而不是你“以为”的结构。











