我遇到了一个奇怪的问题。我试图添加一个外键到一个引用另一个表,但由于某种原因失败了。以我对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

当前回答

你只需要回答一个问题

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

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

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

不能在数据条目后添加外键的原因是由于表不一致,您将如何处理一个新的外键对前数据填充的表?

如果答案是否定的,那么按照其他指示进行。

其他回答

截断表,然后尝试添加FK约束。

我知道这个解决方案有点尴尬,但它确实100%有效。但我同意这不是解决问题的理想方案,但我希望它能有所帮助。

很可能您的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;

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

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

    SHOW TABLE STATUS WHERE Name =  't1';

    ALTER TABLE t1 ENGINE=InnoDB;

你可以试试这个例子

 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,只需取消启用外键检查

为例

希望这个解决方案能解决你的问题:)

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

你的子列中是否存在父列中不存在的值(除了NULL,如果子列为空) 子列和父列是否具有相同的数据类型? 您所引用的父列上是否有索引?MySQL似乎出于性能原因需要这样做(http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html) 这个为我解决了这个问题:两个表是否具有相同的排序规则?

一个表是UTF-8格式,另一个表是iso-something格式。这并没有起作用。将iso-table更改为UTF-8排序规则后,可以毫无问题地添加约束。在我的例子中,phpMyAdmin甚至没有在创建外键约束的下拉菜单中显示iso-encoding的子表。