我有一个最初在MyISAM中的数据库,因此没有外键约束。因此,有很多孤立的行,其中外键引用的记录已被删除。
为了解决这个问题,我决定转换为InnoDB并添加外键,使用CASCADE进行更新和删除。但是,当我尝试添加外键时,我得到这样的错误(来自Navicat 8控制台):
1452 - Cannot add or update a child row: a foreign key constraint fails
(`database`.`#sql-1358_38d`, CONSTRAINT `#sql-1358_38d_ibfk_1` FOREIGN KEY
(`manufacturerID`) REFERENCES `manufacturer` (`ID`) ON DE)
我知道为什么会这样做 - 因为孤立的行。有没有办法让约束的创建自动清除那些行?完成所有表并找到孤立的行需要很长时间。
这是我正在运行的一个查询,以防它被怀疑:
ALTER TABLE part_number ADD CONSTRAINT
FOREIGN KEY(manufacturerID)
REFERENCES manufacturer(ID)
ON DELETE CASCADE
ON UPDATE CASCADE;
答案 0 :(得分:2)
编写查找孤立行的查询,然后使用该查询删除。 e.g
SELECT part_number.id FROM part_number LEFT JOIN manufacturer ON (manufacturer.ID = part_number.manufacturerID) where manufacturer.ID IS NULL
答案 1 :(得分:1)
在添加约束之前,您需要删除所有不相关的记录。
你可以采取两种方式。
DELETE FROM part_number
WHERE NOT EXISTS (
select id from manufacturer
where part_number.manufacturerID = manufacturer.ID
)
-- create a temporary table
CREATE TEMPORARY TABLE `temp_ids`
(
`id` INTEGER
);
-- store all id's that need to be deleted
INSERT INTO `temp_ids`
SELECT part_number.id FROM part_number LEFT JOIN manufacturer ON (manufacturer.ID = part_number.manufacturerID)
WHERE ISNULL(`manufacturer.ID);
-- delete them
DELETE
FROM part_number
WHERE id IN (
SELECT `id` FROM `temp_ids`
);
-- drop the table
DROP TEMPORARY TABLE `temp_ids`;
请参阅我的相关问题:Handling database integrity
删除所有“死”记录后,您将能够添加约束。
希望这适合你:)