为什么这个MySQL插件因外键约束错误而失败?

时间:2014-09-26 22:46:57

标签: 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`, 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中的主键约束设置为(subjektID, lokacijaID),还引用subjektID引用subjekt.subjektID的外键,因此我删除了该主键并添加了额外的auto_incrementlokacijaSubjektaID作为主键,但没有任何更改。

编辑:以下是按要求提供的表格说明:

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:我能够通过删除表subjekt并将其与所有外键重新创建,然后重新填充数据来解决此问题。在执行此操作时,我注意到引用subjekt的其他一些表在引用列上具有错误的签名,然后是更多引用这些表的表,这基本上在数据库中的大多数表上级联。当我修复所有签名不匹配并恢复外键约束时,我可以将数据插入lokacijaSubjekta而不会出现进一步的问题。

3 个答案:

答案 0 :(得分:1)

错误主要是说您为外键列(INSERT中的第二列) '1' 提供的值未找到 subjectID表格的subjekt列。

从您展示的所有内容来看,价值就在那里。 MySQL通常在数值上下文中解释字符串文字,并且它应该计算为整数值1。 sql_mode中的某些设置可能会使MySQL比默认情况下更“严格”。检查sql_mode

的设置
SHOW VARIABLES LIKE 'sql_mode'

您可以尝试在字符串文字中添加0,

SELECT '1'+0  and verify it returns integer value of 1.

您也可以在INSERT语句中尝试,或尝试删除单引号,但我认为这不会有所作为(除了sql_mode的一些奇怪设置)。

你说你已经确认没有任何触发器干扰INSERT。

要考虑的其他一些可能性:

作为交易的一部分,另一个会话是否将subjekID = 1的行插入subjekt,并且尚未发布COMMIT? (如果您正在使用InnoDB,请执行SHOW INNODB STATUS命令以获取有关上一个外键错误的更多信息。)

是否重命名了subjekt表的前一个版本,移动到另一个数据库,并创建了一个新的subjekt表?现有外键引用与其引用的表“保持”,它可能引用另一个模式中的“旧”表。您可以检查information_schema.constraints表,检查表的架构以及引用的表。

由于subjektID是PRIMARY KEY,我们不希望InnoDB索引损坏是一个问题。

检查完这些东西之后,我很难过。

是否可能存在无效数据,在FOREIGN_KEY_CHECKS被禁用时插入数据...并且在此会话中FOREIGN_KEY_CHECKS已启用,并且此插入语句导致InnoDB“检查”表中的一些其他行,而不仅仅是正在插入的行?

什么存储引擎?什么版本的MySQL?

这是一个难题。

答案 1 :(得分:0)

您应该使用 Default or 0 而不是 null ,如果您在某些时候更正了引用,则应断开IDE并重新连接它。

尝试:

insert into lokacijaSubjekta (lokacijaSubjektaID, subjektID, lokacijaID) values (Default, '1', '1');

答案 2 :(得分:0)

可能是因为您已将字符串分隔符放在整数值周围,将它们转换为char值:

... values (NULL, '1', '1');

而不是

... values (NULL, 1, 1);

插入char'1'的Ascii值而不是值1.

此外,如果lokacijaSubjektaID是自动增量值,则应尝试在其中插入Null值。您需要从insert语句中完全删除此列。