377

我正在尝试将我的新架构转发到我的数据库服务器上,但我无法弄清楚为什么会出现此错误。

我试图在这里寻找答案,但我发现的所有内容都表明要么将数据库引擎设置为 InnoDB,要么确保我试图用作外键的键是它们自己表中的主键. 如果我没记错的话,这两件事我都做过。我还可以做些什么?

Executing SQL script in server

ERROR: Error 1215: Cannot add foreign key constraint

-- -----------------------------------------------------
-- Table `Alternative_Pathways`.`Clients_has_Staff`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Clients_has_Staff` (
  `Clients_Case_Number` INT NOT NULL ,
  `Staff_Emp_ID` INT NOT NULL ,
  PRIMARY KEY (`Clients_Case_Number`, `Staff_Emp_ID`) ,
  INDEX `fk_Clients_has_Staff_Staff1_idx` (`Staff_Emp_ID` ASC) ,
  INDEX `fk_Clients_has_Staff_Clients_idx` (`Clients_Case_Number` ASC) ,
  CONSTRAINT `fk_Clients_has_Staff_Clients`
    FOREIGN KEY (`Clients_Case_Number` )
    REFERENCES `Alternative_Pathways`.`Clients` (`Case_Number` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Clients_has_Staff_Staff1`
    FOREIGN KEY (`Staff_Emp_ID` )
    REFERENCES `Alternative_Pathways`.`Staff` (`Emp_ID` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

SQL 脚本执行完成:语句:7 成功,1 失败

这是父表的 SQL。

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Clients` (
  `Case_Number` INT NOT NULL ,
  `First_Name` CHAR(10) NULL ,
  `Middle_Name` CHAR(10) NULL ,
  `Last_Name` CHAR(10) NULL ,
  `Address` CHAR(50) NULL ,
  `Phone_Number` INT(10) NULL ,
  PRIMARY KEY (`Case_Number`) )
ENGINE = InnoDB

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Staff` (
  `Emp_ID` INT NOT NULL ,
  `First_Name` CHAR(10) NULL ,
  `Middle_Name` CHAR(10) NULL ,
  `Last_Name` CHAR(10) NULL ,
  PRIMARY KEY (`Emp_ID`) )
ENGINE = InnoDB
4

29 回答 29

667

我猜测Clients.Case_Number和/或与和不Staff.Emp_ID完全相同的数据类型。Clients_has_Staff.Clients_Case_NumberClients_has_Staff.Staff_Emp_ID

也许父表中的列是INT UNSIGNED

它们在两个表中的数据类型必须完全相同。

于 2013-06-06T18:08:27.093 回答
276

您可能会收到外键约束错误的原因:

  1. 您没有使用 InnoDB 作为所有表的引擎。
  2. 您正在尝试引用目标表上不存在的键。确保它是另一个表上的(它可以是主键或唯一键,或者只是一个key
  3. 列的类型不相同(例外是引用表上的列可以为空,即使它在被引用表中不可为空)。
  4. 如果主键或外键是 varchar,请确保两者的排序规则相同。
  5. 原因之一也可能是您使用的列ON DELETE SET NULL未定义为空。因此,请确保该列设置为默认空值。

检查这些。

于 2013-06-06T18:11:28.553 回答
96

对于其他人,相同的错误可能并不总是由于列类型不匹配。您可以通过发出命令找到有关 MySQL 外键错误的更多信息

SHOW ENGINE INNODB STATUS;

您可能会在打印的消息顶部附近发现错误。就像是

在被引用的表中找不到被引用的列作为第一列出现的索引,或者表中的列类型与被引用的表的约束不匹配。

于 2014-07-08T14:55:51.617 回答
14

错误 1215 是一个令人讨厌的错误。爆炸丸的答案涵盖了基础知识。你要确保从那里开始。但是,还有更多、更微妙的情况需要注意:

例如,当您尝试链接不同表的 PRIMARY KEY 时,请确保提供正确的ON UPDATEON DELETE选项。例如:

...
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `t` (`other_id`) ON DELETE SET NULL
....

不会飞,因为 PRIMARY KEYs(例如id)不能是NULL.

我敢肯定,在添加此类约束时还会出现更多类似的微妙问题,这就是为什么在遇到约束错误时,请始终确保约束及其含义在您当前的上下文中有意义。祝您的错误 1215 好运!

于 2014-12-01T08:56:32.097 回答
10

检查表的排序规则。使用SHOW TABLE STATUS,您可以检查有关表的信息,包括排序规则。

两个表必须具有相同的排序规则。

它发生在我身上。

于 2018-01-29T03:53:18.320 回答
7

就我而言,我使用SET FOREIGN_KEY_CHECKS=0, 然后删除了一个表SET FOREIGN_KEY_CHECKS=1。当我去重新加载表时,我得到了error 1215. 问题是数据库中有另一个表具有我已删除并正在重新加载的表的外键。重新加载过程的一部分涉及更改其中一个字段的数据类型,这使另一个表中的外键无效,从而触发error 1215. 我通过删除然后使用相关字段的新数据类型重新加载另一个表来解决问题。

于 2014-05-08T17:51:00.033 回答
5

我在尝试添加外键时遇到了同样的错误。就我而言,问题是由标记为无符号的外键表的主键引起的。

于 2013-11-12T23:47:21.070 回答
5

在使用Laravel 4 时,尤其是使用 JeffreyWay 的 Laravel 4 生成器时,我遇到了“错误 1215:无法添加外键约束”的陷阱。

在 Laravel 4 中,您可以使用 JeffreyWay 的 Generators 生成迁移文件来一张一张地创建表,也就是说,每个迁移文件都会生成一张表。

您必须知道每个迁移文件的生成都带有文件名中的时间戳,这为文件提供了顺序。当您触发 Artisan CLI 命令时,生成顺序也是迁移操作的顺序php artisan migrate

因此,如果文件要求外键约束引用将在后一个文件中生成但尚未生成的键,则会触发错误 1215 。

在这种情况下,您必须调整迁移文件的生成顺序。以正确的顺序生成新文件,将内容拷贝进去,然后删除杂乱无章的旧文件。

于 2013-12-06T09:08:26.413 回答
3

我有同样的问题。

我这样做解决了它:

我在 primary key: (id int(11) unsigned NOT NULL AUTO_INCREMENT)

尝试在我的模式生成器中导入表后,我发现了这个解决方案。

于 2014-03-30T15:11:14.330 回答
3

我有同样的问题,我的解决方案是:

前:

CREATE TABLE EMPRES
( NoFilm smallint NOT NULL

  PRIMARY KEY (NoFilm)

  FOREIGN KEY (NoFilm) REFERENCES cassettes

);

解决方案:

CREATE TABLE EMPRES
(NoFilm smallint NOT NULL REFERENCES cassettes,

 PRIMARY KEY (NoFilm)

);
于 2015-04-28T21:57:33.423 回答
3

我只是想为VARCHAR外键关系添加这种情况。上周我试图在 MySQL Workbench 8.0 中解决这个问题,并最终能够修复该错误。

简短回答: 模式、表、列、引用表、引用列以及引用父表的任何其他表的字符集和排序规则必须匹配。

长答案: 我的表中有一个 ENUM 数据类型。我将其更改为VARCHAR,我可以从参考表中获取值,这样我就不必更改父表来添加其他选项。这种外键关系看起来很简单,但我得到了 1215 错误。arvind的回答和以下链接建议使用

SHOW ENGINE INNODB STATUS;

在使用这个命令时,我得到了以下关于错误的详细描述,没有额外的有用信息

在被引用的表中找不到被引用的列作为第一列出现的索引,或者表中的列类型与被引用的表的约束不匹配。请注意,使用 >= InnoDB-4.1.12 创建的表中 ENUM 和 SET 的内部存储类型发生了变化,并且旧表中的此类列不能被新表中的此类列引用。有关正确的外键定义,请参阅http://dev.mysql.com/doc/refman/8.0/en/innodb-foreign-key-constraints.html

之后,我按照Arvind BharadwajSET FOREIGN_KEY_CHECKS=0;的建议使用了这里的链接:

这给出了以下错误消息:

错误代码:1822。添加外键约束失败。缺少约束索引

此时,我对模式进行了“逆向工程”,并且能够在 EER 图中建立外键关系。在“正向工程师”上,我收到以下错误:

错误 1452:无法添加或更新子行:外键约束失败

当我将 EER 图“正向工程师”编辑为新模式时,SQL 脚本运行没有问题。在比较正向工程尝试生成的 SQL 时,我发现不同之处在于字符集和排序规则。父表、子表和两列都有utf8mb4字符集和utf8mb4_0900_ai_ci排序规则,但是,父表中的另一列被引用CHARACTER SET = utf8 , COLLATE = utf8_bin ;到不同的子表。

对于整个架构,我将所有表和所有列的字符集和排序规则更改为以下内容:

CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;

这终于解决了我的 1215 错误问题。

旁注: 排序规则utf8mb4_general_ci适用于 MySQL Workbench 5.0 或更高版本。排序规则utf8mb4_0900_ai_ci仅适用于 MySQL Workbench 8.0 或更高版本。我相信我遇到字符集和排序规则问题的原因之一是由于 MySQL Workbench 升级到 8.0。这是一个链接,更多地讨论了这个排序规则。

于 2018-10-17T21:36:50.577 回答
3

就我而言,我不得不禁用FOREIGN KEY检查,因为源表不存在。

SET FOREIGN_KEY_CHECKS=0;

于 2018-10-03T05:35:15.827 回答
3

检查表兼容性(引擎)与SHOW TABLE STATUS WHERE Name = 'tableName'.

例如,如果一张桌子是 另一张桌子是MyISAMInnoDB您可能会遇到此问题。

您可以通过以下命令对其进行更改:

ALTER TABLE myTable ENGINE = InnoDB;

从文档

于 2017-01-12T00:20:42.463 回答
2

我找不到这个错误

CREATE TABLE RATING (

Riv_Id INT(5),
Mov_Id INT(10) DEFAULT 0,
Stars INT(5),
Rating_date DATE, 

PRIMARY KEY (Riv_Id, Mov_Id),

FOREIGN KEY (Riv_Id) REFERENCES REVIEWER(Reviewer_ID)
ON DELETE SET NULL ON UPDATE CASCADE,

FOREIGN KEY (Mov_Id) REFERENCES MOVIE(Movie_ID)
ON DELETE SET DEFAULT ON UPDATE CASCADE
)
于 2014-08-11T01:07:48.513 回答
2

对我来说,这是列类型。大整数!= 整数。

但后来它仍然没有工作。

所以我检查了引擎。确保 Table1 = InnoDB 和 Table = InnoDB

于 2015-09-10T04:05:14.937 回答
2

另一个原因:如果您使用外键中使用的ON DELETE SET NULL 所有列,则必须允许空值。其他人在这个问题中发现了这一点。

据我了解,数据完整性不会有问题,但似乎 MySQL 不支持此功能(在 5.7 中)。

于 2017-03-06T10:20:15.073 回答
2

对于 MySQL (InnoDB) ...获取要链接的列的定义:

SELECT * FROM information_schema.columns WHERE
TABLE_NAME IN (tb_name','referenced_table_name') AND
COLUMN_NAME  IN ('col_name','referenced_col_name')\G

比较并验证两个列定义具有:

相同的 COLUMN_TYPE(长度),相同的 COLATION

可能有必要禁用/启用 foreign_key 机制,但要注意是否在生产环境中:

set foreign_key_checks=0;
ALTER TABLE tb_name ADD FOREIGN KEY(col_name) REFERENCES ref_table(ref_column) ON DELETE ...
set foreign_key_checks=1;
于 2016-10-24T16:34:25.697 回答
2

当列的类型不同时也会发生这种情况。

例如,如果您引用的列是 UNSIGNED INT 并且被引用的列是 INT,那么您会收到此错误。

于 2015-08-29T06:17:56.947 回答
1

当由于引用的表使用 MyISAM 引擎而发生此错误时,此答案提供了一种快速转换数据库的方法,因此所有 Django 模型表都使用 InnoDB:Converting an existing MyISAM database to InnoDB with Django

这是一个名为convert_to_innodb的 Django 管理命令。

于 2015-01-07T23:45:44.393 回答
1

呜呜呜我刚收到!它混合了许多已经发布的答案(InnoDB、未签名等)。

我在这里没有看到的一件事是:如果您的外键指向主键,请确保源列具有有意义的值。例如,如果主键是 mediumint(8),请确保源列也包含 mediumint(8)。这对我来说是问题的一部分。

于 2015-05-05T22:16:11.990 回答
1

所以我尝试了上面的所有修复,但没有运气。我可能在我的表格中遗漏了错误 - 只是找不到原因,我一直收到错误 1215。所以我使用了这个修复程序。

在 phpMyAdmin 的本地环境中,我从相关表中导出了数据。我选择了 CSV 格式。在选择表的 phpMyAdmin 中时,我选择了“更多->选项”。在这里,我向下滚动到“将表复制到(database.table)。选择“仅结构”。重命名表,也许只是在当前表名旁边添加“复制”一词。单击“开始”这将创建一个新的表。导出新表并将其导入新的或其他服务器。我也在此处使用 phpMyAdmin。导入后,将表的名称更改回其原始名称。选择新表,选择导入。格式选择 CSV .取消选中“启用外键检查”。选择“Go”。到目前为止一切正常。

我在我的博客上发布了我的修复。

于 2020-02-02T22:00:15.700 回答
1

在使用 Laravel 迁移时尝试创建外键时,如下例所示:

用户表

public function up()
{
    Schema::create('flights', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->TinyInteger('color_id')->unsigned();
        $table->foreign('color_id')->references('id')->on('colors');
        $table->timestamps();
    });
}

颜色表

public function up()
{
    Schema::create('flights', function (Blueprint $table) {
        $table->increments('id');
        $table->string('color');
        $table->timestamps();
    });
}

有时属性不起作用:

[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint

发生此错误是因为 [user table] 中的外键(type)与 [colors table] 中的主键(type)不同。

要解决这个问题,你应该改变[colors table]中的主键:

$table->tinyIncrements('id');


使用主键时$table->Increments('id');,应Integer作为外键使用:

$table->unsignedInteger('fk_id');
$table->foreign('fk_id')->references('id')->on('table_name');

当您使用主键时$table->tinyIncrements('id');,您应该使用unsignedTinyInteger外键:

$table->unsignedTinyInteger('fk_id');
$table->foreign('fk_id')->references('id')->on('table_name');

当您使用主键时$table->smallIncrements('id');,您应该使用unsignedSmallInteger外键:

$table->unsignedSmallInteger('fk_id');
$table->foreign('fk_id')->references('id')->on('table_name');

当您使用主键时$table->mediumIncrements('id');,您应该使用unsignedMediumInteger外键:

$table->unsignedMediumInteger('fk_id');
$table->foreign('fk_id')->references('id')->on('table_name');
于 2017-06-16T13:13:45.307 回答
1

由于完全不同的原因,我遇到了这个错误。我使用MySQL Workbench 6.3 来创建我的数据模型(很棒的工具)。我注意到当外键约束定义中定义的列顺序不符合表列顺序时,也会产生这个错误。

我花了大约四个小时尝试其他所有方法,但检查了一下。

现在一切正常,我可以重新开始编码了。:-)

于 2015-12-05T22:08:54.803 回答
0

您还可以检查两个表的引擎都设置为 InnoDB。

于 2021-10-30T12:37:57.583 回答
0

也要注意反引号的使用。我在脚本中有以下语句

ALTER TABLE service ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;

但最后的反引号是错误的。它应该是:

ALTER TABLE service ADD FOREIGN KEY (create_by) REFERENCES `system_user`(`id`);

不幸的是,MySQL 没有提供有关此错误的任何详细信息...

于 2015-08-31T12:06:24.943 回答
0

这是已经说过的微妙版本,但在我的例子中,我有 2 个数据库(foo 和 bar)。我首先创建了 foo,但我没有意识到它引用了 bar.baz 中的外键(尚未创建)。当我尝试创建 bar.baz (没有任何外键)时,我不断收到此错误。看了一会后,我在 foo 中找到了外键。

所以,长话短说,如果你得到这个错误,你可能有一个预先存在的外键到正在创建的表。

于 2017-10-20T04:36:52.713 回答
0

对我来说,1215 错误发生在我导入由创建的转储文件时mysqldump,它按字母顺序创建表,在我的情况下,这导致外键引用文件中稍后创建的表。(对此博客文章的提示:MySQL错误代码1215:“无法添加外键约束”</a>

由于 mysqldump 按字母顺序排列表,并且我不想更改表的名称,因此我按照 JeremyWeir在此页面上的回答中的说明进行操作,该说明指出放在set FOREIGN_KEY_CHECKS = 0;转储文件的顶部并放在转储文件SET FOREIGN_KEY_CHECKS = 1;的底部.

该解决方案对我有用。

于 2019-06-04T00:50:57.617 回答
0

此错误的另一个来源是当您有两个或多个具有相同外键名称的相同表名时。

这有时会发生在使用建模和设计软件(如MySQL Workbench )的人身上,然后从设计中生成脚本。

于 2016-05-06T08:43:42.183 回答
0

除了前面所有关于确保字段定义相同且表类型也具有相同排序规则的建议外,请确保您不会犯新手错误,即尝试链接字段中的数据不存在的字段已经在字段中。如果字段中的数据尚未输入到字段中,则将导致此错误。遗憾的是,错误消息并没有多大帮助。

如果不确定,则备份具有外键的表,删除所有数据,然后尝试创建外键。如果成功了,你就知道该怎么做了!

于 2017-07-02T22:04:14.300 回答