无法添加或更新子行:外键约束失败
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 | |||
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 - 无法添加或更新子行:外键约束失败