Mysql错误1452-无法添加或更新子行:外键约束失败
我有一个奇怪的问题。 我试图添加一个外键引用另一个表,但由于某种原因失败。 由于我对MySQL的知识有限,唯一可能会怀疑的是在引用我想引用的表上的另一个表上有一个外键。
这里是我的表关系的图片,通过phpMyAdmin: 关系生成
我已经在两个表上做了一个SHOW CREATE TABLE
查询, sourcecodes_tags
是带有外键的表, sourcecodes
是被引用的表。
CREATE TABLE `sourcecodes` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) unsigned NOT NULL, `language_id` int(11) unsigned NOT NULL, `category_id` int(11) unsigned NOT NULL, `title` varchar(40) CHARACTER SET utf8 NOT NULL, `description` text CHARACTER SET utf8 NOT NULL, `views` int(11) unsigned NOT NULL, `downloads` int(11) unsigned NOT NULL, `time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `user_id` (`user_id`), KEY `language_id` (`language_id`), KEY `category_id` (`category_id`), CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 CREATE TABLE `sourcecodes_tags` ( `sourcecode_id` int(11) unsigned NOT NULL, `tag_id` int(11) unsigned NOT NULL, KEY `sourcecode_id` (`sourcecode_id`), KEY `tag_id` (`tag_id`), CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=latin1
如果有人能告诉我这里发生了什么事情,那我真的很高兴,我没有接受任何正式的培训或者任何与MySQL有关的事情:)
谢谢。
编辑:这是生成错误的代码:
ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
您的sourcecodes_tags
表格很可能包含sourcecode_id
sourcecodes_tags
表中不存在的sourcecode_id
值。 你必须先摆脱那些。
这是一个查询,可以find这些ID:
SELECT DISTINCT sourcecode_id FROM sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id WHERE sc.id IS NULL;
我有我的MySQL数据库相同的问题,但最终我得到了一个解决scheme,为我工作。
由于在我的表中,从mysql的angular度来看一切都很好(两个表都应该使用Innodb引擎,并且每列的数据types应该是相同的types,它们都参与了外键约束)。
唯一的做法是禁用外键检查,稍后在执行外键操作后启用它。
我采取的步骤:
mysql> SET foreign_key_checks = 0; mysql> alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query OK, 8 rows affected (0.23 sec) Records: 8 Duplicates: 0 Warnings: 0 mysql> SET foreign_key_checks = 1;
使用NOT IN
来查找限制条件 :
SELECT column FROM table WHERE column NOT IN (SELECT intended_foreign_key FROM another_table)
所以,更具体地说:
SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes)
编辑: IN
和NOT IN
运算符已知比JOIN
运算符要快得多,以及更容易构build和重复。
截断表格,然后尝试添加FK约束 。
我知道这个解决scheme有点尴尬,但它确实有效。 但是我同意这不是解决问题的理想解决scheme,但我希望它有帮助。
当将外键设置为parent.id到child.column时,如果child.column的值已经为0并且没有parent.id值为0,也会发生这种情况
您需要确保每个child.column都是NULL或具有存在于parent.id中的值
现在,我读了诺斯写的这个陈述,这就是他正在validation的。
对我来说,这个问题有点不同,超级容易检查和解决。
你必须确保你的表都是InnoDB。 如果其中一个表(即参考表是MyISAM),则约束将失败。
SHOW TABLE STATUS WHERE Name = 't1'; ALTER TABLE t1 ENGINE=InnoDB;
我今天也有同样的问题。 我testing了四件事情,其中一些已经在这里提到:
-
您的子列中是否存在父列中不存在的任何值(除了NULL,如果子列是可空的)
-
子列和父列是否具有相同的数据types?
-
在您参考的父列上是否有索引? 由于性能的原因,MySQL似乎需要这个( http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html )
-
这一个解决了我的问题:两张表的sorting是否一致?
我在utf-8中有一个表,另一个在iso-something中。 那没有用。 在将iso-table改为utf-8归类之后,可以毫无问题地添加约束条件。 在我的情况下,phpMyAdmin甚至没有显示在创build外键约束的下拉列表中的iso编码子表。
我也遇到同样的问题,我检查了我的表的行,发现有一些与我想定义为外键的字段的值不兼容。 我纠正了这些价值,再次尝试,问题解决了。
-
删除你想成为外键的列。
-
再次创build它,但将其默认值设置为NULL。
-
尝试再次将其设置为外键。
这个列可能有一些值,如0,但它们不是真正的外键,所以MySQL不能将该列设置为外键。
我最后删除了我的表中的所有数据,并再次运行更改。 有用。 不是很棒的一个,但它节省了很多时间,特别是你的应用程序还处于开发阶段,没有任何客户数据。
我有三个不同的时间完全相同的问题。 在每种情况下,这是因为我的一个(或多个)logging不符合新的外键。 在尝试添encryption钥本身之前,您可能需要更新现有logging以遵循外键的语法约束。 下面的例子通常应该隔离问题logging:
SELECT * FROM (tablename) WHERE (candidate key) <> (proposed foreign key value) AND (candidate key) <> (next proposed foreign key value)
在你的查询中为外键中的每个值重复AND (candidate key) <> (next proposed foreign key value)
。
如果你有大量的logging,这可能是困难的,但如果你的桌子相当小,不应该花太长的时间。 在SQL语法中我并不是非常棒,但是这一直是我的问题。
清空你的表的数据并运行命令。 它会工作。
我在使用Laravel和雄辩时得到这个错误,试图使一个外键链接会导致一个1452年。问题是缺乏链接表中的数据。
请看这里的例子: http : //mstd.eu/index.php/2016/12/02/laravel-eloquent-integrity-constraint-violation-1452-foreign-key-constraint/
尝试这个
SET foreign_key_checks = 0; ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE SET foreign_key_checks = 1;
我有一个解决scheme,你只需要回答一个问题:
你的表已经存储了数据吗? 特别是表中包含了外键。
如果答案是肯定的,那么你所做的唯一的事情就是删除所有logging,然后你可以自由地添加表中的任何外键。
删除指令:从子项(包括外键表)到父表。
数据input后不能添加外键的原因是由于表的不一致性,你将在原来的数据填充表上处理新的外键?
如果不是,请按照其他说明操作。
我正在准备这个解决scheme,这个例子可能会有所帮助。
我的数据库有两个表(电子邮件和credit_card)与他们的ID主键。 另一个表(客户端)将这个表ID作为外键引用。 我有理由将电子邮件从客户端数据中分离出来。
首先,我插入引用表(email,credit_card)的行数据,然后获得每个ID,第三个表(客户端)需要这些ID。
如果您不先插入引用表中的行,那么当您在引用外键的第三个表中插入一个新行时,MySQL将无法创build对应关系。
如果您首先插入引用表的引用行,那么引用外键的行将不会发生错误。
希望这可以帮助。
UPDATE sourcecodes_tags SET sourcecode_id = NULL WHERE sourcecode_id NOT IN ( SELECT id FROM sourcecodes);
应该有助于摆脱这些ID。 或者,如果在sourcecode_id
不允许使用null
,那么删除这些行或将这些缺less的值添加到sourcecodes
表中。
我有同样的问题,并find解决scheme,在外键列上放置NULL
而不是NOT NULL
。 这是一个查询:
ALTER TABLE `db`.`table1` ADD COLUMN `col_table2_fk` INT UNSIGNED NULL, ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC), ADD CONSTRAINT `col_table2_fk1` FOREIGN KEY (`col_table2_fk`) REFERENCES `db`.`table2` (`table2_id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
MySQL已经执行了这个查询!