当外键存在时,MySQL 5.5外键约束失败

时间:2011-04-06 13:17:49

标签: mysql database foreign-keys foreign-key-relationship mysql5

刚刚在mac os x 10.6上安装了MySQL 5.5,并且在许多表上遇到了一个奇怪的问题。以下是一个例子。插入行失败时带有外键约束,但不应该。它引用的外键确实存在。有什么想法吗?

mysql> show create table Language;
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language | CREATE TABLE `Language` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Code` varchar(2) NOT NULL,
  `Name` varchar(63) CHARACTER SET utf8 DEFAULT NULL,
  `Variant` varchar(63) CHARACTER SET utf8 DEFAULT NULL,
  `Country_Id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Code` (`Code`,`Country_Id`,`Variant`),
  KEY `FKA3ACF7789C1796EB` (`Country_Id`),
  CONSTRAINT `FKA3ACF7789C1796EB` FOREIGN KEY (`Country_Id`) REFERENCES `Country` (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show create table Language_Phrases;
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table            | Create Table                                                                                                                                                                                                                                                                                                                                                    |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language_Phrases | CREATE TABLE `Language_Phrases` (
  `Language_Id` int(11) NOT NULL,
  `Phrase` varchar(255) DEFAULT NULL,
  `Label` varchar(255) NOT NULL,
  PRIMARY KEY (`Language_Id`,`Label`),
  KEY `FK8B4876F3AEC1DBE9` (`Language_Id`),
  CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from Language;
+----+------+----------+---------+------------+
| Id | Code | Name     | Variant | Country_Id |
+----+------+----------+---------+------------+
|  1 | en   | English  |         |        235 |
|  2 | ro   | Romanian |         |        181 |
+----+------+----------+---------+------------+
2 rows in set (0.00 sec)

mysql> select * from Language_Phrases;
Empty set (0.00 sec)

mysql> INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`dev`.`language_phrases`, CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`))
mysql> 

更新 :在多次删除并重新创建数据库之后,我在上面的插入失败后执行了show engine innodb status并获得了令人惊讶的结果。找不到父语言表!这看起来很奇怪......任何想法?

------------------------
LATEST FOREIGN KEY ERROR
------------------------
110406  9:55:49 Transaction:
TRANSACTION CA3B, ACTIVE 0 sec, OS thread id 4494462976 inserting
mysql tables in use 1, locked 1
1 lock struct(s), heap size 376, 0 row lock(s)
MySQL thread id 25, query id 50720 localhost root update
INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase')
Foreign key constraint fails for table `dev`.`language_phrases`:
,
  CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`)
Trying to add to index `PRIMARY` tuple:
DATA TUPLE: 5 fields;
 0: len 4; hex 80000001; asc     ;;
 1: len 17; hex 747970654d69736d617463682e79656172; asc exampleLabel;;
 2: len 6; hex 00000000ca3b; asc      ;;;
 3: len 7; hex 00000000000000; asc        ;;
 4: len 21; hex 59656172206d7573742062652061206e756d626572; asc Some phrase;;

But the parent table `dev`.`Language`
or its .ibd file does not currently exist!

更新2 :事实证明这只是MySQL中的大量错误。显然MySQL的最新版本在mac os X 10.6下可能无法完全运行(可能也是早期的版本?)。降级至5.5.8似乎有效。非常令人惊讶。

6 个答案:

答案 0 :(得分:8)

这似乎是自Mac OS X上的MySQL 5.5.9以来引入的错误: http://bugs.mysql.com/bug.php?id=60309

在5.5.13(5月31日发布)中标记为已修复并在发行说明中提及: http://dev.mysql.com/doc/refman/5.5/en/news-5-5-13.html

或者,我在5.5.10上验证过的错误报告中列出了一种解决方法,并在下面转载:


[20 Mar 11:29] Harald Neiss

I also received a new MBP and reinstalled MySQL (mysql-5.5.10-osx10.6-x86_64). Finally I
came across the same problem as described above. So here is the query result and what I
did to solve it.

mysql> show variables like 'lower%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_file_system | ON    |
| lower_case_table_names | 2     |
+------------------------+-------+
2 rows in set (0.00 sec)

Dropped database, created the file /etc/my.cnf with the following content:

[mysqld]
lower_case_table_names=1

Restarted the MySQL daemon and repeated the query:

mysql> show variables like 'lower%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_file_system | ON    |
| lower_case_table_names | 1     |
+------------------------+-------+
2 rows in set (0.00 sec)

I recreated the tables and everything works fine.

答案 1 :(得分:1)

恕我直言,这并不奇怪。我在MySQL中发现了许多错误。例如,使用where子句运行查询,例如" WHERE some_tinyint_column = 0"它应该不会产生任何数据,但重写该条款为" WHERE(不是some_tinyint_column = 1)"产生结果。经过一些研究后,我发现这是一个应该修复过的bug,但是在我使用的版本中,bug仍然存在。

结论:当某些东西在MySQL中完全没有意义时,我通常会发现它可以安全地假设它是一个错误,并开始研究这些信息。

答案 2 :(得分:0)

检查Language_Phrases (Language_Id)LanguageId

的数字类型属性
  

两者都应该是 UNSIGNED ZEROFILL SIGNED

答案 3 :(得分:0)

* MySQL的> INSERT INTO Language_Phrases(Language_Id,Label,Phrase)VALUES(1,'exampleLabel','some phrase'); 错误1452(23000):无法添加或更新子行:... *

您正在尝试将 1 作为Language_Id插入,但表格语言具有属性AUTO_INCREMENT = 3 。在这种情况下,您应该使用3或更高。

答案 4 :(得分:0)

我今天遇到了同样的错误。在我的例子中,我使用了一个脚本来重新创建一些包含所有记录的表。

事实上,我已经意识到我的表之间的“引擎”类型不同:一个是MyISAM,第二个(FK的引用)是InnoDB。我把所有的表都改成了InnoDB,现在一切正常。

此脚本将生成更新脚本文件(Reference

mysql -u DB_USER -pDB_PASSWORD --default-character-set=utf8  DATABASE_NAME -e "SELECT CONCAT('ALTER TABLE ', table_name, ' ENGINE=InnoDB;') AS sql_statements FROM information_schema.tables AS tb WHERE table_schema = database() AND ENGINE = 'MyISAM' AND TABLE_TYPE = 'BASE TABLE' ORDER BY table_name DESC;" > ./alter_InnoDb.sql

您必须删除“alter_InnoDb.sql”中的第一行,该行包含文本“sql_statements”。

之后,您可以在数据库中执行脚本来更正此错误:

mysql -u DB_USER -pDB_PASSWORD --default-character-set=utf8  DATABASE_NAME < ./ alter_InnoDb.sql

答案 5 :(得分:0)

我也面临着同样的问题,没有找到解决我问题的解决方案。因此,由于多种原因可能会发生此问题。我只是想将所有这些原因和解决方案放在一个地方,并且还要提供有助于解决此问题的解决方案。我希望这会对以后的人有所帮助。

1)由Penfold提供-表名区分大小写
2)父子表中的引擎不匹配
3)父子表中的字符集不匹配
4)Parent(Id)和Child(Patent_Id:两者都必须具有完全相同的数据类型(也已签名/未签名)
5)InnoDB丢失了表,但是表存在-Please find solution here

SQL查询(显示引擎InnoDB状态)给出此错误(其.ibd文件当前不存在!) 引用

6)很少有较早版本的mysql有此错误。Bug#60196Bug#60309
7)这对我有用(如果上面的一切似乎还不错,您可能需要这样做)-从子表中删除外键并再次添加约束。如果它也失败,则删除父表并再次创建它,在此之前,您需要从所有子表中删除外键。这是最后一件事。
进一步阅读:
https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_lower_case_table_names