MySQL 中的外键添加失败,错误代码为 1005,编号为 150

Posted

技术标签:

【中文标题】MySQL 中的外键添加失败,错误代码为 1005,编号为 150【英文标题】:Foreign Key add fails in MySQL with Error Code 1005, number 150 【发布时间】:2011-09-02 03:37:35 【问题描述】:

所以我正在尝试向我的一个表中添加一个新的外键:

 ALTER TABLE `UserTransactions`.`ExpenseBackTransactions` 
   ADD CONSTRAINT `FK_EBTx_CustomAccountID`
   FOREIGN KEY (`CustomAccountID` )
   REFERENCES `UserTransactions`.`CustomAccounts` (`CustomAccountID`)
   ON DELETE NO ACTION
   ON UPDATE NO ACTION,
   ADD INDEX `FK_EBTx_CustomAccountID` (`CustomAccountID` ASC) ;

我不断收到以下错误:

Error Code: 1005
Can't create table './UserTransactions/#sql-187a_29.frm' (errno: 150)

过去我对这个表和其他表进行了相当多的更改,这是我第一次遇到这个问题。有什么想法是什么原因造成的吗?

更新

我的SHOW INNODB STATUS 错误:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
110525 15:56:36 Error in foreign key constraint of table UserTransactions/#sql-187a_2c:

  FOREIGN KEY (`CustomAccountID` )
  REFERENCES `UserTransactions`.`CustomAccounts` (`CustomAccountID` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION
, ADD INDEX `FK_EBTx_CustomAccountID` (`CustomAccountID` ASC):
Cannot resolve table name close to:
 (`CustomAccountID` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION
, ADD INDEX `FK_EBTx_CustomAccountID` (`CustomAccountID` ASC)

【问题讨论】:

SHOW INNODB STATUS 说什么?两列是否具有相同的数据类型(和长度?)?数据库中是否已经有另一个具有该名称的键? FOREIGN KEY 仅支持 InnoDB dev.mysql.com/doc/refman/5.5/en/… 。检查这是否导致问题。 @Ibrahim:myisam 默默地忽略外键规范而不会出错。 【参考方案1】:

有一个nice checklist here。

以下是人们报告的可怕 errno 150 的已知原因的运行列表:

    两个关键字段类型和/或大小不完全匹配。例如,如果一个是 INT(10),则关键字段也需要是 INT(10),而不是 INT(11) 或 TINYINT。您可能希望使用 SHOW CREATE TABLE 确认字段大小,因为查询浏览器有时会直观地显示 INT(10) 和 INT(11) 的 INTEGER。您还应该检查一个未签名,另一个未签名。它们都需要完全相同。 (更多关于已签名与未签名的信息,请点击此处)。 您尝试引用的关键字段之一没有索引和/或不是主键。如果关系中的某个字段不是主键,则必须为该字段创建索引。 (感谢 Venkatesh 和 Erichero 以及终端不连贯的提示) 外键名称是现有键的副本。检查您的外键名称在您的数据库中是唯一的。只需在密钥名称的末尾添加一些随机字符即可进行测试。 (感谢 Niels 提供的提示) 您的一个或两个表是 MyISAM 表。为了使用外键,表必须都是 InnoDB。 (实际上,如果两个表都是 MyISAM,那么您不会收到错误消息 - 它只是不会创建密钥。)在查询浏览器中,您可以指定表类型。 您已在 DELETE SET NULL 上指定了级联,但相关的关键字段设置为 NOT NULL。您可以通过更改级联或将字段设置为允许 NULL 值来解决此问题。 (感谢 Sammy 和 J Jammin) 确保 Charset 和 Collat​​e 选项在表级别以及键列的单个字段级别都相同。 (感谢 FRR 的提示) 您的外键列上有一个默认值(即 default=0)(感谢 Omar 的提示) 关系中的一个字段是组合(复合)键的一部分,并且没有自己的单独索引。即使该字段有一个索引作为复合键的一部分,您也必须仅为该键字段创建一个单独的索引才能在约束中使用它。 (感谢 Alex 的提示) 您的 ALTER 语句中有语法错误,或者您在关系中输入了错误的字段名称(感谢 Christian & Mateo 的提示) 您的外键名称超过了 64 个字符的最大长度。 (感谢 Nyleta 的提示)

【讨论】:

原来这是一个意外创建为 MyISAM 而不是 InnoDB 的表。一种非常有趣的 ID-10-T 错误暴露方式。 如果没有那个清单,我会搜索几个小时......似乎另一个表是在 MySQL 安装还不支持 InnoDB 时创建的。 11.您尝试使用外键引用的表或列存在。这是一件简单的事情,有时像我这样的人会忘记【参考方案2】:

根据我的经验,errno: 150 通常表示键表和关联表中FOREIGN KEY 列的数据类型不相同。确保CustomAccounts.CustomAccountIDExpenseBackTransactions.CustomAccountID 是完全相同的类型,包括UNSIGNED(如果适用)。

如果这没有帮助,请发布SHOW CREATE TABLE ExpenseBackTransactions;SHOW CREATE TABLE CustomAccounts;

【讨论】:

你的意思是show create table,对吧?但除此之外,是的,当场。这很可能是两个表之间的字段类型不匹配。【参考方案3】:

Catch 22。外键需要索引。 MySQL 不会对该查询进行排序,以便在进行外键检查时索引存在。因此,首先创建索引,然后在 2 个单独的查询中添加外键。

【讨论】:

试过了,认为这就是错误所在,但在运行 ADD INDEX 命令后,它最终无法仅使用 ADD CONSTRAINT 命令。 这在旧的 MySQL 版本上是正确的,但在任何最近的 5.x 系列上都不是这样。

以上是关于MySQL 中的外键添加失败,错误代码为 1005,编号为 150的主要内容,如果未能解决你的问题,请参考以下文章

使用 mysql 工作台创建 CHAR 类型的外键时出错:错误 1005:无法创建表(错误号:150)

如何解决无法添加或更新子行:Spring JPA 中的外键约束失败错误?

MySQL 添加表时出现“错误 1005”

mysql添加外键失败

Laravel 4迁移问题中的外键

在 mysql 表上添加外键约束时出现错误 1005