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

Posted

技术标签:

【中文标题】无法添加或更新子行:外键约束失败【英文标题】:Cannot add or update a child row: a foreign key constraint fails 【发布时间】:2011-06-27 16:24:47 【问题描述】:

表 #1:

Field Type Null Key Default Extra
UserID int(11) NO PRI NULL auto_increment
Password varchar(20) NO
Username varchar(25) NO
Email varchar(60) NO

表#2:

Field Type Null Key Default Extra
UserID int(11) NO MUL
PostID int(11) NO PRI NULL auto_increment
Title varchar(50) NO
Summary varchar(500) NO

错误:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: (myapp/table2, 约束 table2_ibfk_1 外键 (UserID) 参考table1 (UserID))

我做错了什么?我读了http://www.w3schools.com/Sql/sql_foreignkey.asp,我看不出有什么问题。

【问题讨论】:

你能发布触发错误的查询吗? 简而言之,您试图在table2.UserID 中插入/更新一个在table1.UserID 中不存在的值。 不知道为什么,但是在将我的数据库从 Windows 环境移动到 Linux 之后,我不得不删除并重新创建一个关系(那时我注意到了这个问题)。该值确实存在,但删除并重新添加关系修复了它。显然,您可能需要非常小心。 【参考方案1】:

您收到此错误是因为您尝试向table2 添加/更新一行,但该行没有基于table1 中当前存储的值的UserID 字段的有效值。如果您发布更多代码,我可以帮助您诊断具体原因。

【讨论】:

PreparedStatement st = connection.prepareStatement("插入 table2 (UserID, PostID, Title, Summary)" + "values (UserID, ?, ?, ?)"); 不确定投反对票的目的是什么;我的回答是完全有效和正确的。 嗯...在准备好的语句中混合命名参数和未命名参数绝对不是一个好主意。它应该是“values (?, ?, ?, ?)”,并在您的执行语句中指定适当的 UserID 值。 所以我需要执行另一个 SQL 语句来从 table1 获取用户 ID? 最有可能是 0 ,如果是这种情况,请用 Null 替换它【参考方案2】:

这意味着您正在尝试向table2 插入一个UserID 值,该值在table1 中不存在。

【讨论】:

我在添加ID为0的外键时有过这种经历,由于该表没有ID为0的记录,因此无法引用其他表中的键【参考方案3】:

一个简单的技巧是在对表执行任何操作之前禁用外键检查。简单查询

SET FOREIGN_KEY_CHECKS=0

这将禁用与任何其他表的外键匹配。完成表格后再次启用它

SET FOREIGN_KEY_CHECKS=1

这对我有用很多次。


请注意,您在执行此操作时会进入危险区。虽然肯定有有效的用例,但只有在确定您了解其中的含义时才应该这样做。

【讨论】:

我如何使用这个?? @SachinfromPune 只需添加 SET FOREIGN_KEY_CHECKS=0;在 mysql 文件和 SET FOREIGN_KEY_CHECKS=1 开始时;在mysql文件末尾,重新导入数据 这不是问题吗?你失去了参照完整性,对吧? 正确索引条目的存在支持参照完整性。只要您的键和索引正确,您应该能够在批量输入期间禁用键检查。【参考方案4】:

我发现了另一个奇怪的情况:如果你不小心创建了一个从 InnoDB 表到 MyISAM 表的外键,即使数据在其他方面是有效的,MySQL 也会在插入时抛出这个错误。

见http://nick.zoic.org/art/mysql-foreign-key-error/

【讨论】:

是的,我也有同样的问题。两个表应该是 InnoDB! 我遇到了同样的问题,谢谢你的提示。这是关于如何将表从 MyISAM 转换为 InnoDB dev.mysql.com/doc/refman/5.7/en/… TLDR 的 MySQL 文档链接:ALTER TABLE table_name ENGINE=InnoDB; 确实,我的数据库就是这种情况。我决定将 MyISAM 引擎更改为 InnoDB。最后,我可以按照我想要的方式使用数据库。 我花了几个小时寻找答案,终于谢谢你!【参考方案5】:

您收到此错误是因为 table1.UserID 上不存在一些值 int table2.UserID(我猜您在创建此外键之前已手动设置了 table2.UserID 值)。 此场景的一个示例:table1.UserID 获取值 1,2,3 和 table2.UserID 获取值 4(手动添加)。所以当你制作外键时,他们无法从table1 中找到UserID = 4,就会出现错误。 要修复此错误,只需从table2 中删除UserID = 4,或者您可以将它们都清空,然后创建外键and。 祝你好运!

【讨论】:

【参考方案6】:

我花了一段时间才弄清楚。简单来说,引用另一个表的表中已经有数据,并且它的一个或多个值在父表中不存在。

例如 表2有以下数据:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

表1

UserID    Password    Username    Email
9         ********    JohnDoe     john@example.com

如果您尝试 ALTER table2 并添加外键,则查询将失败,因为 Table1 中不存在 UserID=5。

【讨论】:

【参考方案7】:

如果你在表2中创建外键之前已经在表1中插入了一行,那么你会得到一个外键约束错误,因为自增值在表1中是2,在表2中是1。解决这个问题您必须截断表 1 并将自动增量值设置回 1。然后您可以添加表 2。

【讨论】:

【参考方案8】:

确保您已将数据库引擎设置为 InnoDB,因为在 MyISAM 中不支持外键和事务

【讨论】:

ALTER TABLE my_table ENGINE = InnoDB;【参考方案9】:

稍微修正一下: 使表 1 中的 JoinColumn 'nullable = true' 和表 2 中的 'UserID' 字段 'insertable=false' 和 'nullable=true'。

在 Table1 实体中:

@OneToMany(targetEntity=Table2.class, cascade = CascadeType.ALL)
@JoinColumn(name = "UserID", referencedColumnName = "UserID", nullable = true)
private List<Table2> table2List;

在 Table2 实体中:

@Column(insertable = false, nullable = true)
private int UserID;

【讨论】:

这个答案完全解决了我的问题,非常感谢你分享这个。对我来说,关键是在我用作子对象/表中的 foraeing 键的字段上添加 @Column(insertable=false, nullable=true)。【参考方案10】:

我刚遇到同样的问题,解决方法很简单。

您正在尝试在父表中不存在的子表中添加一个 id。

检查好,因为InnoDB有有时会增加auto_increment列而不增加值的bug,例如INSERT ... ON DUPLICATE KEY

【讨论】:

认真的吗? 不要插入不存在的 id 引用 ...只需检查【参考方案11】:

我遇到了类似的问题。您正在尝试在具有内容且列不可为空的表上应用外键。你有两个选择。

    使要应用外键约束的列可以为空。这样,外键就会应用,因为知道某些字段可以为空。 (这就是我所做的。) 创建要对其应用外键约束的列,编写查询以将外键插入该列,然后应用外键约束。 (没试过,但是应该可以的

【讨论】:

【参考方案12】:

确保您插入外键的值存在于父表中。这对我有帮助。例如,如果您将user_id = 2 插入table.2,但table.1 没有user_id = 2,则约束将引发错误。准确地说,我的是错误代码#1452。希望这可以帮助其他有同样问题的人!

【讨论】:

【参考方案13】:

我遇到了同样的问题,原因是我在添加外键之前在第一个表中有一行。

【讨论】:

【参考方案14】:

删除table2的UserID字段的索引。它适合我

【讨论】:

【参考方案15】:

我也遇到了同样的问题,问题是我的父表条目值与外键表值不匹配。 所以请在清除所有行后尝试..

【讨论】:

约束要求表2中引用的用户已经在表1中定义。【参考方案16】:

如果其他人提供的解决方案不起作用。然后您应该尝试检查父表和子表的数据库引擎。在我的情况下,我将父表的引擎设置为“MyISAM”,将其更改为 InnoDB 修复它。

希望这可以帮助像我一样陷入困境的其他人。

【讨论】:

【参考方案17】:

您不应该在数据库中针对级联放置 ondelete 字段。

所以将 onDelete 字段设置为 RESTRICT

祝你好运♥

【讨论】:

【参考方案18】:

又一个奇怪的案例给了我这个错误。我错误地将我的外键引用到 id 主键。这是由不正确的 alter table 命令引起的。我通过查询 INFORMATION_SCHEMA 表 (See this *** answer) 发现了这一点

该表非常混乱,无法通过任何 ALTER TABLE 命令修复。我终于放下了桌子并重建了它。这摆脱了完整性错误。

【讨论】:

【参考方案19】:

也许当您添加userID 列时,该特定表的数据已建立,因此默认值为0,请尝试添加不带NOT NULL 的列

【讨论】:

【参考方案20】:

我也收到此错误:“无法添加或更新子行:外键约束失败”。向父表添加新行时出现错误

问题是外键约束是在父表而不是子表上定义的。

【讨论】:

【参考方案21】:

如果您使用mysql索引或表之间的关系,首先您删除列(例如:city_id)并创建具有相同名称的新列(例如:city_id)。然后再试一次......

【讨论】:

【参考方案22】:

表中是否包含任何现有数据? 如果是这样,请尝试清除要添加外键的表中的所有数据。 然后再次运行代码(添加外键)。

我多次遇到这个问题。当您想在现有表上添加外键时,清除表中的所有数据有效。

希望这可行:)

【讨论】:

【参考方案23】:

当您要添加具有父表主键中不存在的值的外键时,会发生该错误。您必须确保 table2 中的新外键 UserID 具有 table1 主键中存在的值,有时默认为 null 或等于 0。

您可以先用 table1 的主键中存在的值更新 table2 中外键的所有字段。

update table2 set UserID = 1 where UserID is null

如果您想添加不同的用户 ID,您必须使用所需的值修改每一行。

【讨论】:

【参考方案24】:

子表外键约束失败

由于以下原因,可能会出现此问题:

如果是在Spring mvc中做,需要显式描述id类型,因为有时候mysql无法识别id的类型。所以你在实体类的两个表中明确设置为@GeneratedValue (strategy = GenerationType.IDENTITY)

【讨论】:

以上是关于无法添加或更新子行:外键约束失败的主要内容,如果未能解决你的问题,请参考以下文章

MySql 重启后:#1452 - 无法添加或更新子行:外键约束失败

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

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

SQLSTATE[23000]:完整性约束违规 1452 无法添加或更新子行:外键约束失败

Django“无法添加或更新子行:外键约束失败”

完整性约束违规:1452 无法添加或更新子行:外键约束失败