我正在使用MySQL。我们假设我有一个包含两列的表hierarchy
:id
,parent_id
。
parent_id
引用同一个表中其他行的id
,所以我在那里有外键。
hierarchy
表包含一些数据,但它们现在不相关。
我还有一个名为new_hierarchy_entries
的第二个表,它具有相同的列,但没有设置外键限制。
new_hierarchy_entries
包含:
id parent_id
2 1
1 null
现在我想将new_hierarchy_entries
中的所有行复制到hierarchy
。当我天真地跑:
INSERT INTO hierarchy SELECT * FROM new_hierarchy_entries
我收到错误:无法添加或更新子行:外键约束失败(my_db。hierarchy
,CONSTRAINT hierarchy_ibfk_2 FOREIGN KEY(parent_id)REFERENCES hierarchy
(id))
当然,如果逐行插入行,则无法插入第一行(id = 2,parent = 1),因为表hierarchy
中没有id = 1的行。
另一方面,如果一次添加所有行,则将满足约束。那么如何以这样的方式复制行,以确保复制后满足约束,但复制时可能不满足?
按new_hierarchy_entries
排序id
行无济于事。我不能假设parent_id < id
在同一行。
按层次结构对new_hierarchy_entries
行进行排序(使用树术语,先给我留下,然后让他们的父母等等)会有所帮助,但我不确定如何在MySQL查询中这样做。< / p>
我想暂时关闭FOREIGN_KEY_CHECKS。但后来我可以插入不一致的数据,我不会发现。打开FOREIGN_KEY_CHECKS并不会使数据库检查所有数据的一致性。无论如何,这需要太多的资源。
答案 0 :(得分:0)
这很棘手。启用FOREIGN_KEY_CHECKS后,我不知道有什么办法让MySQL重新检查外键引用。
您可以检查自己的孤儿行,如果有,请回滚。
BEGIN;
SET SESSION FOREIGN_KEY_CHECKS=0;
INSERT INTO hierarchy SELECT * FROM new_hierarchy_entries;
SET SESSION FOREIGN_KEY_CHECKS=1;
SELECT COUNT(*) FROM hierarchy AS c
LEFT OUTER JOIN hierarchy AS p ON p.id=c.parent_id
WHERE p.id IS NULL;
-- if count == 0 then...
COMMIT;
-- otherwise ROLLBACK and investigate the bad data
另一种可能性是使用带有IGNORE选项的INSERT,它将跳过失败的行。然后在循环中重复相同的语句,只要您看到“受影响的行”超过0。
INSERT IGNORE INTO hierarchy SELECT * FROM new_hierarchy_entries;
INSERT IGNORE INTO hierarchy SELECT * FROM new_hierarchy_entries;
INSERT IGNORE INTO hierarchy SELECT * FROM new_hierarchy_entries;
...