243

我有一个奇怪的问题。我正在尝试将外键添加到一个引用另一个表的表中,但由于某种原因它失败了。由于我对 MySQL 的了解有限,唯一可能怀疑的是在另一个表上存在一个外键,该表引用了我试图引用的表。

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

这是生成错误的代码:

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
4

21 回答 21

229

您的表很可能sourcecodes_tags包含您的表中sourcecode_id不再存在的值sourcecodes。你必须先摆脱那些。

这是一个可以找到这些 ID 的查询:

SELECT DISTINCT sourcecode_id FROM 
   sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id 
WHERE sc.id IS NULL;
于 2009-08-10T07:38:52.130 回答
105

我的 MySQL 数据库也遇到了同样的问题,但最后,我得到了一个对我有用的解决方案。
因为从 mysql 的角度来看,在我的表中一切都很好(两个表都应该使用 InnoDB 引擎,并且每列的数据类型应该是参与外键约束的相同类型)。
我唯一做的就是禁用外键检查,然后在执行外键操作后启用它。
我采取的步骤:

SET foreign_key_checks = 0;
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
SET foreign_key_checks = 1;
于 2012-02-04T07:29:54.733 回答
56

用于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)

编辑:众所周知INNOT IN运算符比运算符快得多JOIN,而且更容易构造和重复。

于 2011-05-31T20:16:01.843 回答
23

Truncate the tables and then try adding the FK Constraint.

I know this solution is a bit awkward but it does work 100%. But I agree that this is not an ideal solution to deal with problem, but I hope it helps.

于 2013-05-29T04:31:21.273 回答
17

对我来说,这个问题有点不同,而且超级容易检查和解决。

您必须确保您的两个表都是 InnoDB。如果其中一个表,即引用表是 MyISAM,则约束将失败。

    SHOW TABLE STATUS WHERE Name =  't1';

    ALTER TABLE t1 ENGINE=InnoDB;
于 2013-03-29T18:32:54.550 回答
16

如果 child.column 的值已经为 0 并且没有 parent.id 值为 0,则在将 parent.id 的外键设置为 child.column 时也会发生这种情况

您需要确保每个 child.column 为 NULL 或具有 parent.id 中存在的值

现在我阅读了 nos 所写的声明,这就是他正在验证的内容。

于 2011-10-21T20:42:54.003 回答
14

我今天遇到了同样的问题。我测试了四件事,其中一些已经在这里提到:

  1. 您的子列中是否有任何值在父列中不存在(除了 NULL,如果子列可以为空)

  2. 子列和父列是否具有相同的数据类型?

  3. 您引用的父列上是否有索引?MySQL 似乎出于性能原因需要这样做(http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html

  4. 而这个为我解决了这个问题:两张表是否有相同的排序规则?

我有一张 UTF-8 表,另一张表是 iso-something。那没有用。将 iso-table 更改为 UTF-8 排序规则后,可以毫无问题地添加约束。就我而言,phpMyAdmin 甚至没有在下拉菜单中以 iso-encoding 显示子表以创建外键约束。

于 2013-04-24T10:27:39.153 回答
9

似乎第 0 列的某些无效值不是有效的外键,因此 MySQL 无法为其设置外键约束。

您可以按照以下步骤操作:

  1. 删除您尝试为其设置 FK 约束的列。

  2. 再次添加它并将其默认值设置为 NULL。

  3. 尝试再次为其设置外键约束。

于 2015-08-13T05:38:13.620 回答
5

我遇到了同样的问题,我检查了表的行,发现与我想定义外键的字段的值有些不兼容。我更正了这些值,再试一次,问题就解决了。

于 2012-12-23T00:56:55.930 回答
4

我最终删除了表中的所有数据,然后再次运行 alter。有用。不是很出色,但它节省了很多时间,尤其是您的应用程序仍处于开发阶段,没有任何客户数据。

于 2012-01-09T09:49:27.603 回答
4

尝试这个

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;
于 2017-07-25T01:48:21.887 回答
2

你只需要回答一个问题:

您的表是否已经存储数据?(特别是包含外键的表。)

如果答案是肯定的,那么您唯一需要做的就是删除所有记录,然后您可以自由地将任何外键添加到您的表中。

删除指令:从子表(包括外键表)到父表。

数据输入后无法添加外键的原因是由于表不一致,您将如何处理以前填充数据的表上的新外键?

如果答案是否定的,则按照其他说明进行操作。

于 2015-04-26T09:05:15.570 回答
2

我在三个不同的时间遇到​​了完全相同的问题。在每种情况下,都是因为我的一个(或多个)记录不符合新的外键。在尝试添加键本身之前,您可能希望更新现有记录以遵循外键的语法约束。下面的例子一般应该隔离问题记录:

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)在查询中重复外键中的每个值。

如果您有大量记录,这可能会很困难,但如果您的表相当小,则不会花费太长时间。我在 SQL 语法方面并不是特别出色,但这对我来说总是孤立的问题。

于 2012-08-28T14:04:10.093 回答
2

清空两个表的数据并运行命令。它会起作用的。

于 2015-04-23T08:59:23.450 回答
2

我在使用 Laravel 和 eloquent 时遇到此错误,尝试建立外键链接会导致 1452。问题是链接表中缺少数据。

请在此处查看示例: http: //mstd.eu/index.php/2016/12/02/laravel-eloquent-integrity-constraint-violation-1452-foreign-key-constraint/

于 2016-12-02T11:42:25.863 回答
1

我正在准备这个解决方案,这个例子可能会有所帮助。

我的数据库有两个表(email 和 credit_card),它们的 ID 具有主键。另一个表(客户端)将此表 ID 称为外键。我有理由将电子邮件与客户数据分开。

首先,我为引用的表(电子邮件、信用卡)插入行数据,然后您获取每个表的 ID,这些 ID 在第三个表(客户端)中是需要的。

如果您不首先在引用的表中插入行,那么当您在引用外键的第三个表中插入新行时,MySQL 将无法进行对应。

如果先为被引用的表插入被引用的行,然后是引用外键的行,则不会发生错误。

希望这可以帮助。

于 2016-03-16T01:40:52.107 回答
1

确保该值在另一个表中,否则您将在分配的相应列中收到此错误。

因此,如果将其分配的列分配给另一个表的行 id,请确保该表中有一行,否则会出现此错误。

于 2018-01-02T23:38:45.073 回答
1

你可以试试这个例子

 START TRANSACTION;
 SET foreign_key_checks = 0;
 ALTER TABLE `job_definers` ADD CONSTRAINT `job_cities_foreign` FOREIGN KEY 
 (`job_cities`) REFERENCES `drop_down_lists`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
 SET foreign_key_checks = 1;
 COMMIT;

注意:如果您使用的是 phpmyadmin,只需取消选中启用外键检查

例如 _ 在此处输入图像描述

希望这个解决方案可以解决您的问题:)

于 2018-09-13T18:50:54.037 回答
0
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
  SELECT id FROM sourcecodes);

应该有助于摆脱这些ID。或者,如果null中不允许sourcecode_id,则删除这些行或将这些缺失值添加到sourcecodes表中。

于 2016-02-23T14:29:26.167 回答
0

就我而言,我创建了一个具有相同结构的新表,创建了与其他表的关系,然后从有问题的旧表中提取 CSV 中的数据,然后将 CSV 导入新表并禁用外键检查并禁用导入中断,我的所有数据都成功插入到没有问题的新表中,然后删除了旧表。

它对我有用。

于 2019-10-07T07:50:33.957 回答
0

我遇到了同样的问题并找到了解决方案,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 已经执行了这个查询!

于 2017-01-31T07:55:08.773 回答