我有一个表
companies
,其中有一些重复的行,我用一个简单的GROUP BY name
找到了。
这个
companies
表有一个 PRIMARY KEY id
,它在其他几个表中被引用,名称为 company_id
,我也在 INFORMATION_SCHEMA
上的查询中找到了它。
现在我的要求:将两个
companies
合并为一个,意思是update
所有引用的company_id
引用两者中的第一个id,然后删除第二个company
所有
FOREIGN KEYS
都已经用 ON UPDATE CASCADE
子句声明,但我不确定是否有一种聪明的方法可以完成最终结果,而无需手动更新所有引用的 FOREIGN KEYS
我的直觉是
mark_to_delete
并将其设置为 1 所有重复的 companies
我想删除FOREIGN_KEY_CHECKS=0
避免在将 company.ID
更新为现有的时出现错误companies
即 mark_to_delete=1
FOREIGN_KEY_CHECKS=1
显然我最大的疑问是
FOREIGN_KEY_CHECKS
如何工作,我尝试阅读文档并搜索我的具体案例,但我不明白ON UPDATE CASCADE
是否有效。
我认为最坏的情况是列出所有引用的公司 ID,在表上运行更新,并将引用的 ID 设置为“健康”公司,然后删除重复的公司。
你不需要改变
FOREIGN_KEY_CHECKS
,你也不需要考虑ON UPDATE CASCADE
。
你所说的“最坏情况”实际上更容易。
识别重复的公司。假设带有
id
1、2、14、39 的公司彼此重复。
选择一个作为该给定公司的规范行。假设它是 1。
将子表中的任何引用更新为其他重复的公司 ID:
UPDATE other_table SET company_id = 1
WHERE company_id IN (2, 14, 39);
这不需要更改
FOREIGN_KEY_CHECKS
,因为 company_id
引用满足 UPDATE 之前和之后的约束。
这不会产生
ON UPDATE CASCADE
。级联适用于您更新引用的主键,但您并没有这样做。您正在更改子表中的外键。
对引用
companies
的任何其他表格重复此操作。
一旦
companies
中的重复行在子表中没有引用,您就可以随意删除它们。
DELETE FROM companies WHERE id IN (2, 14, 39);
我建议在选择规范行之前仔细检查
companies
的所有其他列。其中任何一个都可能包含有用的数据(例如当前的电话号码),您必须读取它们并手动合并。
UPDATE slave
JOIN main m1 USING (main_id)
JOIN ( SELECT MIN(main_id) main_id, main_name
FROM main m2
GROUP BY 2
) m3 USING (main_name)
SET slave.main_id = m3.main_id;
SELECT * FROM main;
SELECT * FROM slave;
SELECT * FROM main JOIN slave USING (main_id);