如何在MySQL表中合并两个冗余记录,保持所有PK / FK关系?

时间:2011-03-08 19:00:40

标签: php mysql merge foreign-keys redundancy

假设我有一个包含以下字段和记录的表customers

id   first_name   last_name   email                  phone
------------------------------------------------------------------------
1    Michael      Turley      mturley@whatever.com   555-123-4567
2    John         Dohe        jdoe@whatever.com      
3    Jack         Smith       jsmith@whatever.com    555-555-5555
4    Johnathan    Doe                                123-456-7890

还有其他几个表,例如ordersrewardsreceipts,其外键customer_id与此表的customers.id相关。

正如您所看到的,我的用户以他们的无限智慧为John Doe创建了重复记录,并且拼写不一致且数据丢失。管理员注意到这一点,选择客户2和4,然后单击“合并”。然后提示他们为每个字段选择哪个值是正确的等等,我的PHP确定合并的记录应如下所示:

id   first_name   last_name   email                  phone
------------------------------------------------------------------------
?    John         Doe         jdoe@whatever.com      123-456-7890

让我们假设Doe先生已经下了几个订单,获得了奖励,生成了收据......但是其中一些已经与id 2相关联,而且有些与id 4相关联。合并的行需要匹配所有的外国人其他表中与原始行匹配的键。

这是我不知道该怎么做的地方。我的直觉是这样做:

DELETE FROM customers WHERE id = 4;

UPDATE customers
SET first_name = 'John',
    last_name  = 'Doe',
    email      = 'jdoe@whatever.com',
    phone      = '123-456-7890'
WHERE id = 2;

UPDATE orders, rewards, receipts
SET customer_id = 2
WHERE customer_id = 4;

我认为这样可行,但是如果稍后我添加另一个具有customer_id外键的表,我必须记得返回并将该表添加到我的合并函数中的第二个UPDATE查询中,否则可能会失去完整性

必须有更好的方法来做到这一点。

4 个答案:

答案 0 :(得分:6)

我来到谷歌这是我的2美分:

SELECT `TABLE_NAME` 
FROM `information_schema`.`KEY_COLUMN_USAGE` 
WHERE REFERENCED_TABLE_SCHEMA='DATABASE'
  AND REFERENCED_TABLE_NAME='customers'
  AND REFERENCED_COLUMN_NAME='customer_id'

添加db for insurance(你永远不会知道有人复制db的时候)。

不是寻找列名,而是在这里查看外键本身

如果您更改了删除限制以限制在删除/迁移子项之前无法删除任何内容

答案 1 :(得分:2)

简短的回答是,没有更好的方法(我能想到的)。

这是一种权衡。如果您发现有很多这样的实例,那么在添加新客户之前花一些时间来编写一个更强大的算法来检查现有客户可能是值得的(即检查姓/名的变化,将其呈现给任何添加的人客户,如果他们真的想要添加这个新客户,请询问他们2到3次,等等。如果没有很多这样的实例,那么可能不值得投资。

除此之外,你的方法是我能想到的唯一方法。我实际上会删除这两个记录,并使用合并的数据创建一个新记录,从而产生新的客户ID而不是重新使用旧记录,但这只是个人偏好 - 在功能上它与您的方法相同。您仍然需要记住返回并修改合并功能以反映customer.id字段上的新关系。

答案 2 :(得分:1)

至少,要防止任何触发删除导致一些级联效应,我会先做

更新SomeTable设置CustomerID = CorrectValue,其中CustomerID = WrongValue

(在所有表格中都这样做)......

THEN 从CustomerID = WrongValue

的客户中删除

至于重复数据......如果你缺少某些信息,试着找出哪个“Will Smith,Bill Smith,William Smith”......有些人可能是完全合法的不同的人。

答案 3 :(得分:0)

作为我评论的更新:

use information_schema;
select table_name from columns where column_name = 'customer_id';

然后遍历生成的表并相应地更新。

就个人而言,我会使用你的本能解决方案,因为如果有包含需要免除的customer_id列的表,这可能会很危险。