MySQL使用外键创建表,给出错误:150

96 mysql foreign-keys mysql-error-150

我试图在MySQL中创建一个带有两个外键的表,它引用了另外两个表中的主键,但是我得到一个错误:150错误,它不会创建表.

这是所有3个表的SQL:

CREATE TABLE role_groups (
  `role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
  `name` varchar(20),
  `description` varchar(200),
  PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `roles` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `description` varchar(200),
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;

create table role_map (
  `role_map_id` int not null `auto_increment`,
  `role_id` int not null,
  `role_group_id` int not null,
  primary key(`role_map_id`),
  foreign key(`role_id`) references roles(`role_id`),
  foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激.

小智 236

我遇到了同样的问题ALTER TABLE ADD FOREIGN KEY.

一小时后,我发现必须满足这些条件才能得到错误150:

  1. 在定义外键以引用它之前,父表必须存在.您必须按正确的顺序定义表:首先是父表,然后是子表.如果两个表互相引用,则必须创建一个没有FK约束的表,然后创建第二个表,然后将FK约束添加到第一个表中ALTER TABLE.

  2. 这两个表必须都支持外键约束,即ENGINE=InnoDB.其他存储引擎默默地忽略外键定义,因此它们不返回错误或警告,但不保存FK约束.

  3. Parent表中引用的列必须是键的最左侧列.如果父母的密钥是PRIMARY KEY或者最好UNIQUE KEY.

  4. FK定义必须以与PK定义相同的顺序引用PK列.例如,如果FK REFERENCES Parent(a,b,c)则不能按顺序在列上定义Parent的PK (a,c,b).

  5. Parent表中的PK列必须与Child表中的FK列具有相同的数据类型.例如,如果父表中的PK列是UNSIGNED,请确保为UNSIGNED子表字段中的相应列定义.

    例外:字符串的长度可能不同.例如,VARCHAR(10)可以参考VARCHAR(20),反之亦然.

  6. 任何字符串类型的FK列必须与相应的PK列具有相同的字符集和排序规则.

  7. 如果Child表中已存在数据,则FK列中的每个值都必须与父表PK列中的值匹配.使用如下查询检查:

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL;
    
    Run Code Online (Sandbox Code Playgroud)

    这必须返回零(0)个不匹配的值.显然,这个查询是一个通用的例子; 您必须替换您的表名和列名.

  8. Parent表和Child表都不能是TEMPORARY表.

  9. Parent表和Child表都不能是PARTITIONED表.

  10. 如果使用该ON DELETE SET NULL选项声明FK ,则FK列必须可为空.

  11. 如果声明外键的约束名称,则约束名称在整个模式中必须是唯一的,而不仅仅是在定义约束的表中.两个表可能没有自己的具有相同名称的约束.

希望这可以帮助.

  • 这包括诸如`int(11)unsigned NOT NULL` vs`int(11)NOT NULL`之类的内容. (25认同)
  • 如果表定义为ENGINE = MyISAM,则它不生成errno 150,因为它*忽略*外键声明.这就像说避免汽车发动机故障的最佳方法是开船.:-) (12认同)
  • 还有一件事值得补充:如果父表的PK多于一个字段,则FK中字段的顺序必须与PK中的顺序相同 (4认同)
  • ALTER TABLE table_name ENGINE = InnoDB; (4认同)
  • 此外,如果您的CONSTRAINT的"ON DELETE"规则是"SET NULL",请确保外键实际上可以为NULL!我花了30分钟一遍又一遍地阅读这个答案,确保我的表满足条件但仍然得到错误150.然后我注意到我的FK是一个NOT NULL字段意味着规则是不可能应用的. (2认同)

and*_*otn 62

MySQL的通用"errno 150"消息" 意味着没有正确形成外键约束."正如您可能已经知道如果您正在阅读此页面,通用的"errno:150"错误消息实际上是无益的.然而:

您可以通过运行然后在输出中查找来获取实际的错误消息.SHOW ENGINE INNODB STATUS;LATEST FOREIGN KEY ERROR

例如,这种尝试创建外键约束:

CREATE TABLE t1
(id INTEGER);

CREATE TABLE t2
(t1_id INTEGER,
 CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id));
Run Code Online (Sandbox Code Playgroud)

因错误而失败Can't create table 'test.t2' (errno: 150).除了它是一个外键问题之外,这并没有告诉任何人有用的东西.但跑步SHOW ENGINE INNODB STATUS;,它会说:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130811 23:36:38 Error in foreign key constraint of table test/t2:
FOREIGN KEY (t1_id) REFERENCES t1 (id)):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Run Code Online (Sandbox Code Playgroud)

它说问题是找不到索引.SHOW INDEX FROM t1表明表中根本没有任何索引t1.修复此问题,例如,定义主键t1,将成功创建外键约束.

  • `SHOW ENGINE INNODB STATUS'帮助我立即找出了我一直想要诊断的问题近一个小时.谢谢. (4认同)

Jon*_*ley 25

确保您尝试使用约束链接的两个字段的属性完全相同.

通常,ID列上的"unsigned"属性会引起您的注意.

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL;
Run Code Online (Sandbox Code Playgroud)


Bre*_*ode 10

运行此脚本时,数据库的当前状态是什么?它完全是空的吗?从头开始创建数据库时,您的SQL运行正常,但是errno 150通常与删除和重新创建属于外键的表有关.我感觉你没有使用100%全新的数据库.

如果您在"源"处理SQL文件时出错,您应该能够在"source"命令之后立即从MySQL提示符运行命令"SHOW ENGINE INNODB STATUS"以查看更详细的错误信息.

您可能还想查看手册条目:

如果重新创建已删除的表,则它必须具有符合引用它的外键约束的定义.它必须具有正确的列名和类型,并且必须在引用的键上具有索引,如前所述.如果不满足这些,MySQL将返回错误号1005并在错误消息中引用错误150.如果MySQL从CREATE TABLE语句报告错误号1005,并且错误消息引用错误150,则表创建失败,因为未正确形成外键约束.

- MySQL 5.1参考手册.


Eri*_* L. 5

对于通过 Google 找到此 SO 条目的其他人:请确保您没有尝试对定义为“NOT NULL”的外键(待)列执行 SET NULL 操作。这引起了极大的挫败感,直到我记得检查引擎 INNODB 状态。


jua*_*ala 5

对于正在查看具有相同问题的此线程的人:

得到这样的错误有很多原因.有关MySQL中外键错误的原因和解决方案的完整列表(包括此处讨论的那些),请查看此链接:

MySQL外键错误和Errno 150