1. 出现报错
- 在进行mysq关系l数据库到neo4j图数据库转换的时候,转换规则涉及到外键,所以需要对之前的mysql数据集添加外键。
- 添加过程中出现以上错误。
2. 解决方案
网上最常见的一种解决方案是:
# 切换到外键有问题的那个表,关闭外键检查约束
alter table_name SET FOREIGN_KEY_CHECKS=0;
# 设置外键(一般是修改时添加外键约束)
ALTER TABLE <数据表名> ADD CONSTRAINT <索引名>
FOREIGN KEY(<列名>) REFERENCES <主表名> (<列名>);
# 然后把这个表的外键检查给设置回1
alter table_name SET FOREIGN_KEY_CHECKS=1;
这种方案其实违背了外键的约束性,直接把检查关掉了,那么你设置的外键是否符合数据库设计规则就无法保证。数据库模式可能就不是很好。
同时,出现这个问题,肯定不是mysql数据库抽风了,故意搞你。肯定是你的表有问题,或者是你设置有问题,找到这个原因才更重要
参考:
3. 追溯原因
造成这个错误的原因很多,我整理了一下。
3.1 简单的原因
1. 同一个数据库中外键名称要唯一
比如上面,外键名为:poet_ibfk_1
如果直接使用Navicat这类工具,这个外键名称是自动帮你生成的,ibfk是InnoDB Foreign Key的缩写。外键的一种常用命名方式是表名_fk_序号
,“icity”表中的第一个外键就是“icity_fk_1”
当然,如果是自己直接sql语句插入的,那需要注意。
2. 外键设置错了表(我的错误)
搞不清Navicat中参照表,被参照表和外键的关系,概念模糊,所以报错。而且不容易发现!
比如对于下面的数据库来说,设置外键的时候,应该在poet_to_poem
和verse_to_poem
上设置,我一开始就设置在其他三个单表里,所以就报错了!
3.2 棘手的原因
- 如果是像上面只是命名有问题,那属于个人代码的失误。这种是比较简单的
- 但是如果是由于违反了数据库设计中关于外键的限制(也就是数据本身的数据有问题,或者数据之间的引用有问题),那就不好改了。。
- 上面关闭外键检查,来把这个外键插入,其实是避开了数据库本身存在的问题,其实并不推荐。关于外键的理论,比较长,放在了另一个博客:数据库外键理论及MySQL外键实现规定
1. 取值有问题
参考:数据库外键理论及MySQL外键实现规定
举例来说,有一个诗人表,还有一个诗人诗歌对应表,后者引用前者的诗人id。如果对后面的表设置外键,报错。那么很有可能是因为诗人诗歌表中的诗人id,有不属于诗人表的(不是引用自诗人表),对于这些诗人id,要么就是删掉整列,要么就是把对应行的诗人id这个属性取空值。
2. 表有问题
- 可能引用(参照)表和目标表,使用的存储引擎不同,一般都要求是InnoDB。
- 可能引用表上对应的外键列没有建立索引!(MySQL要求建立,这样可以加快外键检查的速度,而不用扫描整张表)
参考: