为什么此MySQL插入失败并出现外键约束错误?
我在这里不知所措。我无法理解此插入失败的原因:为什么此MySQL插入失败并出现外键约束错误?,mysql,sql,insert,foreign-keys,Mysql,Sql,Insert,Foreign Keys,我在这里不知所措。我无法理解此插入失败的原因: insert into lokacijaSubjekta (lokacijaSubjektaID, subjektID, lokacijaID) values (NULL, '1', '1'); 它失败于: ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`nano`.`lokacijaSubjekta`, CONSTRAI
insert into lokacijaSubjekta (lokacijaSubjektaID, subjektID, lokacijaID) values (NULL, '1', '1');
它失败于:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`nano`.`lokacijaSubjekta`, CONSTRAINT `fk_lokacijaSubjekta_subjekt1` FOREIGN KEY (`subjektID`) REFERENCES `subjekt` (`subjektID`) ON DELETE CASCADE ON UPDATE CASCADE)
以下是密钥的设置方式:
show index from lokacijaSubjekta;
+------------------+------------+-----------------------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+-----------------------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| lokacijaSubjekta | 0 | PRIMARY | 1 | lokacijaSubjektaID | A | 0 | NULL | NULL | | BTREE | |
| lokacijaSubjekta | 1 | fk_lokacijaSubjekta_lokacija1_idx | 1 | lokacijaID | A | 0 | NULL | NULL | | BTREE | |
| lokacijaSubjekta | 1 | fk_lokacijaSubjekta_subjekt1 | 1 | subjektID | A | 0 | NULL | NULL | | BTREE | |
+------------------+------------+-----------------------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
show index from subjekt;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| subjekt | 0 | PRIMARY | 1 | subjektID | A | 35603 | NULL | NULL | | BTREE | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
这是表中的数据:
select * from subjekt where subjektID=1;
+-----------+---------------+
| subjektID | subjektPravni |
+-----------+---------------+
| 1 | 1 |
+-----------+---------------+
select * from lokacija where lokacijaID = 1;
+------------+------------------+------------------+
| lokacijaID | geografskaSirina | geografskaDuzina |
+------------+------------------+------------------+
| 1 | NULL | NULL |
+------------+------------------+------------------+
select * from lokacijaSubjekta;
Empty set (0.00 sec)
起初,我认为这是因为我在lokacijaSubjekta
中将主键约束设置为(subkektid,lokacijaID)
,还有一个来自subkektid
引用subkekt.subkektid
的外键,因此,我删除了主键并添加了一个额外的auto_increment
列lokacijaSubjektaID
,以用作主键,但没有任何更改
编辑:根据要求,以下是表格说明:
describe subjekt;
+---------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+-------+
| subjektID | int(11) unsigned | NO | PRI | NULL | |
| subjektPravni | tinyint(1) | NO | | 0 | |
+---------------+------------------+------+-----+---------+-------+
describe lokacija;
+------------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------------+------+-----+---------+----------------+
| lokacijaID | int(11) | NO | PRI | NULL | auto_increment |
| geografskaSirina | decimal(18,12) | YES | | NULL | |
| geografskaDuzina | decimal(18,12) | YES | | NULL | |
+------------------+----------------+------+-----+---------+----------------+
describe lokacijaSubjekta;
+--------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+------------------+------+-----+---------+----------------+
| lokacijaSubjektaID | int(11) unsigned | NO | PRI | NULL | auto_increment |
| subjektID | int(11) unsigned | NO | MUL | NULL | |
| lokacijaID | int(11) | NO | MUL | NULL | |
+--------------------+------------------+------+-----+---------+----------------+
没有触发器
show triggers;
Empty set (0.01 sec)
编辑2:我可以通过删除表subsekt
并重新创建它和所有外键,然后重新填充数据来解决这个问题。在执行此操作时,我注意到其他一些引用了subjectkt
的表在引用列上的符号不匹配,然后更多的表引用了这些表,这基本上级联到了数据库中的大多数表上。当我修复了所有签名不匹配并恢复了外键约束时,我可以将数据插入到lokacijaSubjekta
,而不会出现进一步的问题。您应该使用而不是null,如果您在某个时候更正了引用,您应该断开IDE并重新连接它
尝试:
可能是因为您在整数值周围放置了字符串分隔符,将它们转换为字符值:
... values (NULL, '1', '1');
而不是
... values (NULL, 1, 1);
插入字符“1”的Ascii值,而不是值1
另外,如果lokacijaSubjektaID是一个自动增量值,那么应该尝试在其中插入一个Null值。您需要从insert语句中完全删除此列。错误本质上是说您为外键列(insert中的第二列)提供的值
'1'
在subjectit
表的subjectID
列中找不到
从你所展示的一切来看,这个值似乎在那里。MySQL通常会像在数字上下文中那样解释字符串文字,它的计算结果应该是整数值1
。sql_模式中的某些设置可能使MySQL比默认设置更“严格”。检查sql_模式的设置
SHOW VARIABLES LIKE 'sql_mode'
您可以尝试向字符串文本添加0
SELECT '1'+0 and verify it returns integer value of 1.
您也可以在INSERT语句中尝试,或者尝试删除单引号,但我认为这不会有什么不同(除了一些奇怪的sql_模式设置)
你说你已经确认没有任何触发器干扰插入
应考虑的其他一些可能性:
subsekid=1的行是否由另一个会话作为事务的一部分插入到subsekt
中,并且尚未发出COMMIT
?(如果您使用的是InnoDB,请执行SHOW InnoDB STATUS
命令以获取有关上次外键错误的更多信息。)
subsekt
表的前一个版本是否已重命名、移动到其他数据库,并创建了新的subsekt
表?现有外键引用它所引用的表“停留”,它可能引用另一个架构中的“旧”表。您可以检查信息\u schema.constraints
表,检查表的模式和引用表的模式
由于subsektid是主键,我们不希望InnoDB索引损坏成为问题
检查完这些东西后,我很困惑
是否可能已经存在无效数据,在禁用外键检查时插入了数据。。。在这个会话中,启用了FOREIGN\u KEY\u CHECKS
,正是这个insert语句使InnoDB“检查”了表中的其他行,而不仅仅是被插入的行
什么存储引擎?什么版本的MySQL
这是一个难题。您似乎在lokacijaSubjekta
中将NULL
赋值给主键
。所有列的数据类型是什么?有任何触发器吗?@PM77-1我可以这样做,因为该列是auto_increment
,MySQL将自动分配密钥。与您拥有的有什么不同?它是什么版本的MySQL?我看到修复后没有外键约束错误,我能知道错误是什么吗?我不知道插入主键中提供的值对外键约束冲突有什么影响。(但是使用Default
代替NULL
关键字对我来说是新的。)使用0
代替NULL
应该会得到相同的结果,除非sql\u模式
包括零上没有自动值
。从INSERT中省略AUTO_INCREMENT主键列也会得到相同的结果。还有另一个subsekt
的化身,但我删除了它,并用一个新的subsekt
替换了它。它肯定不会出现在另一个数据库中,因为这是我唯一在使用的数据库,而现在我是唯一在使用它的数据库。我希望如此。在任何情况下,您的答案都是非常有用的。@Nikola Novak:我的答案中省略了如何检查子表中是否存在具有“无效”外键值的任何现有行,反连接模式:SELECT COUNT(1)from lokacijaSubjekta c LEFT join subjectt p ON p.subjecttid=c.subjecttid,其中p.subjectid为NULL
或者您可以使用不存在(相关子查询)
查看计数是否为零。(如果大于0,则存在无效的非空外键值。)(我不确定在查询运行时是否应禁用foreign\u key\u checks
;如果优化器可能“知道”计数为零,而不实际执行操作
SELECT '1'+0 and verify it returns integer value of 1.