MySQL错误1215:无法添加外键约束

Rob*_*t B 314 mysql foreign-keys

我正在尝试将我的新架构转发到我的数据库服务器上,但我无法弄清楚为什么我收到此错误.我试图在这里搜索答案,但我发现的所有内容都说要么将数据库引擎设置为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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Ike*_*ker 561

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

也许父表中的列是INT UNSIGNED

它们需要在两个表中完全相同的数据类型.

  • 它也可能是字符集不同.我讨厌这个问题,其中一列有utf8字符集而另一列有latin1.使用ALTER TABLE`Table`轻松修复CHARACTER SET = utf8; 和ALTER TABLE`Device` CHANGE COLUMN`ID``ID`CHAR(36)CHARACTER SET'utf8'NOT NULL; (12认同)
  • 谢谢.事实证明这是个问题.Staff.Emp_ID是一个SMALLINT,而引用列是一个INT.有时这是小事...... (9认同)
  • @ www.jensolsson.se你是对的,如果PK包含一个或多个字符串列,那么它们必须使用相同的字符集*和*collat​​ion.在这种特定情况下,PK是INT,因此表和/或列的字符集不相关. (3认同)
  • 整理是我的问题,latin1 与 utf8(检查表格和列)。 (2认同)

Exp*_*lls 222

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

  1. 您没有将InnoDB用作所有表的引擎.
  2. 您正尝试在目标表上引用不存在的键.确保它是另一个表上的(它可以是主键或唯一键)
  3. 列的类型不相同(例外情况是引用表上的列可以为空).
  4. 如果PK/FK是varchar,请确保两者的排序规则相同.

更新:

  1. 其中一个原因可能是您使用的列ON DELETE SET NULL未定义为null.因此,请确保将列设置为默认值null.

检查这些.

  • 我只想补充说,如果FK在字符列上,我认为它们需要具有相同的字符集和整理.(或者可能是1字节和2字节字符集不兼容.) (14认同)
  • 我有另一个原因=)```ON DELETE CASCADE ON UPDATE SET NULL:```你定义了一个SET NULL条件,虽然有些列被定义为NOT NULL.所以,我只修复FK定义. (6认同)
  • 我的理由是你指出了第一个"两个表的不同数据库引擎,InnoDB和MyISAM" (3认同)
  • 也可能的失败是目标字段上**缺少索引**。 (2认同)

小智 81

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

SHOW ENGINE INNODB STATUS;
Run Code Online (Sandbox Code Playgroud)

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

在引用的表中找不到索引,其中引用的列显示为第一列,或者表中的列类型与引用的表不匹配约束.

  • 这是我认为最好的答案,因为它有助于诊断!谢谢. (12认同)

Dom*_*omi 12

错误1215是令人讨厌的.Explosion Pill的答案涵盖了基础知识.你想确保从那里开始.但是,还有更多,更微妙的案例需要注意:

例如,当您尝试连接起来,不同的表的主键,确保提供适当ON UPDATEON DELETE选项.例如:

...
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `t` (`other_id`) ON DELETE SET NULL
....
Run Code Online (Sandbox Code Playgroud)

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

我确信,在添加这些约束时,还有更多类似的微妙问题,这就是为什么遇到约束错误时,总是要确保约束及其含义在您当前的上下文中有意义.祝你的错误1215好运!

  • 此外,从文档:MySQL需要外键和引用键上的索引,以便外键检查可以快速,不需要表扫描.在引用表中,必须有一个索引,其中外键列以相同的顺序*列为第一列*.如果引用表不存在,则会自动在引用表上创建此索引.如果您创建另一个可用于强制执行外键约束的索引,则可以稍后以静默方式删除此索引.如果给定,则使用index_name,如前所述. (2认同)

Car*_*ina 8

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

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

它发生在我身上.


Cod*_*Med 7

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


bor*_*nac 6

对于 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
Run Code Online (Sandbox Code Playgroud)

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

相同的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;
Run Code Online (Sandbox Code Playgroud)


小智 5

我在尝试添加 fk 时遇到了同样的错误。在我的情况下,问题是由标记为未签名的 FK 表的 PK 引起的。


小智 5

在使用Laravel 4时,我遇到了"错误1215:无法添加外键约束"的缺陷,特别是与JeffreyWay的Laravel 4 Generators.

在Laravel 4中,您可以使用JeffreyWay的Generators生成迁移文件以逐个创建表,这意味着每个迁移文件生成一个表.你必须要意识到每个迁移文件与文件名中的时间戳,这给文件的顺序产生的事实.新一代的顺序也迁移操作的顺序,当你火的工匠CLI命令"PHP工匠迁移".因此,如果文件要求引用将在后一个文件中生成但尚未生成的密钥的外键约束,则会触发错误1215.在这种情况下,您需要做的是调整迁移文件生成的顺序.以正确的顺序生成新文件,复制内容,然后删除无序的旧文件.


Den*_*nis 5

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

例如,如果一张表是MyISAM,另一张表是InnoDB,则您可能会遇到此问题。

您可以通过以下命令更改它:

ALTER TABLE myTable ENGINE = InnoDB;
Run Code Online (Sandbox Code Playgroud)

来自文档