合并在其他表中作为外键引用的表行

问题描述 投票:0回答:2

我有一个表

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 设置为“健康”公司,然后删除重复的公司。

mysql merge foreign-keys constraints cascade
2个回答
0
投票

你不需要改变

FOREIGN_KEY_CHECKS
,你也不需要考虑
ON UPDATE CASCADE

你所说的“最坏情况”实际上更容易。

  1. 识别重复的公司。假设带有

    id
    1、2、14、39 的公司彼此重复。

  2. 选择一个作为该给定公司的规范行。假设它是 1。

  3. 将子表中的任何引用更新为其他重复的公司 ID:

    UPDATE other_table SET company_id = 1
    WHERE company_id IN (2, 14, 39);
    

    这不需要更改

    FOREIGN_KEY_CHECKS
    ,因为
    company_id
    引用满足 UPDATE 之前和之后的约束。

    这不会产生

    ON UPDATE CASCADE
    。级联适用于您更新引用的主键,但您并没有这样做。您正在更改子表中的外键。

  4. 对引用

    companies
    的任何其他表格重复此操作。

  5. 一旦

    companies
    中的重复行在子表中没有引用,您就可以随意删除它们。

    DELETE FROM companies WHERE id IN (2, 14, 39);
    

我建议在选择规范行之前仔细检查

companies
的所有其他列。其中任何一个都可能包含有用的数据(例如当前的电话号码),您必须读取它们并手动合并。


0
投票
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);

完整的小提琴样本

© www.soinside.com 2019 - 2024. All rights reserved.