为什么此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.