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


174

表格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: 
Cannot add or update a child row: a foreign key constraint fails 
(`myapp/table2`, CONSTRAINT `table2_ibfk_1` FOREIGN KEY (`UserID`) 
REFERENCES `table1` (`UserID`)) 

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


4
您可以发布触发错误的查询吗?
阻尼

38
简而言之,您尝试插入/更新table2.UserID中不存在的值table1.UserID
Joe Stefanelli

不知道为什么,但是在将数据库从Windows环境迁移到Linux之后,我不得不删除并重新创建一个关系(这是我注意到该问题的时候)。该值确实存在,但是删除并重新添加该关系后将其固定。显然,您可能需要非常小心。
johnsnails

Answers:


234

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


PreparedStatement st = connection.prepareStatement(“插入表2(用户ID,PostID,标题,摘要)” +“值(用户ID,?,?,?)”);
汤姆(Tom)

15
不知道什么是反对票;我的答案是完全正确和正确的。
Brian Driscoll'2

嗯...在准备好的语句中将命名参数与未命名参数混合绝对不是一个好主意。它应该是“值(?,?,?,?)”,并具有您execute语句中指定的UserID的适当值。
Brian Driscoll

因此,我需要对另一个SQL语句执行操作以从table1获取用户ID?
汤姆(Tom)

5
很有可能是0,如果有的话,将其替换为Null
Jeffrey NicholsonCarré13年

123

这意味着您正在尝试插入中不存在table2UserIDtable1


104

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

SET FOREIGN_KEY_CHECKS=0

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

SET FOREIGN_KEY_CHECKS=1

这对我很有效。


我该如何使用?

2
@SachinfromPune只需添加SET FOREIGN_KEY_CHECKS = 0; 在启动mysql文件时,SET FOREIGN_KEY_CHECKS = 1;在mysql文件末尾,重新导入数据
inrsaurabh

1
这不是问题吗?您失去参照完整性,对吗?
roadrunner19年

存在正确的索引条目可支持引用完整性。只要正确设置了键和索引,就应该能够在批量输入期间禁用键检查。
Vernon Keenan

46

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

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


1
是的,我有同样的问题。两个表应该是InnoDB!
emeraldhieu 2015年

2
我也遇到了同样的问题,谢谢小费。下面是MySQL文档的链接了解如何从表中的MyISAM转换成InnoDB的dev.mysql.com/doc/refman/5.7/en/... TLDR:ALTER TABLE TABLE_NAME ENGINE = InnoDB的;
Guilherme Vaz

确实,我的数据库就是这种情况。我决定将MyISAM引擎更改为InnoDB。最后,我可以按照自己的方式使用数据库。
麦克,

17

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


11

这花了我一段时间才能弄清楚。简而言之,引用另一个表的表中已经有数据,并且其一个或多个值在父表中不存在。

例如,Table2具有以下数据:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

表格1

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

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


10

如果在表2中创建外键之前在表1中插入了一行,则将收到外键约束错误,因为表1中的自动增量值为2,表2中的自动增量值为1。要解决此问题,您必须截断表1并将自动增量值设置回1。然后可以添加表2。



7

稍作修复: 在表1中将JoinColumn设置为“ nullable = true”,在表2中将“ UserID”字段设置为“ insertable = false”和“ nullable = true”。

在表1实体中:

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

在表2实体中:

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

这个答案完全解决了我的问题,非常感谢您的分享。对我来说,关键是在我用作子对象/表中的前摄键的文件上添加@Column(insertable = false,nullable = true)。
Israelm

6

我只是有同样的问题,解决方案很容易。

您试图在子表中添加一个在父表中不存在的ID 。

请检查一下,因为InnoDB的错误有时会增加auto_increment列而不添加值,例如, INSERT ... ON DUPLICATE KEY


认真吗?不要插入不存在的ID引用 ...只需检查
Blaztix

5

我有一个类似的问题。您试图在具有内容且该列不可为空的表上应用外键。您有两个选择。

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

4

确保要插入到外键中的值在父表中存在。那对我有帮助。例如,如果您插入user_id = 2table.2,但table.1没有一个user_id = 2,那么约束会引发错误。我的是确切的错误代码#1452。希望这可以帮助其他有相同问题的人!


3

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


1

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


该约束要求在表1中已经定义了表2中引用的用户。
sorak

1

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

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



0

另一个奇怪的情况给了我这个错误。我错误地将我的外键引用为id主键。这是由不正确的alter table命令引起的。我通过查询INFORMATION_SCHEMA表发现了这一点(请参阅此stackoverflow答案)

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


0

也许在您添加该userID列的同时,该特定表已经建立了一个数据,因此其默认值为0,请尝试添加不包含该列的列NOT NULL


0

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

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


0

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


0

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

我多次遇到此问题。当您想在现有表上添加外键时,这种清除表中所有数据的方法起作用。

希望这有效:)


0

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


-1

子表外键约束失败

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

如果在Spring mvc中进行操作,则需要显式描述id类型,因为有时mysql无法识别id类型。因此您在实体类的两个表中都明确设置为@GeneratedValue (strategy = GenerationType.IDENTITY)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.