10

假设我有一个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

还有其他几个表,例如orders, rewards,它们具有与该表相关的receipts外键。customer_idcustomers.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

4 回答 4

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'

添加用于保险的数据库(您永远不会知道何时有人复制数据库)。

与其查找列名,不如在这里查看外键本身

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

于 2011-06-03T13:05:14.140 回答
2

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

这是一个权衡。如果您发现有很多这样的情况,可能值得花一些时间编写一个更强大的算法来在添加新客户之前检查现有客户(即检查名字/姓氏的变化,将它们呈现给添加的人客户,问他们 2 或 3 次他们是否真的确定要添加这个新客户,等等)。如果这些实例不多,那么可能不值得投资。

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

于 2011-03-08T19:07:07.747 回答
2

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

更新 SomeTable 设置 CustomerID = CorrectValue where CustomerID = WrongValue

(在所有表格中执行此操作)...

THEN 从 CustomerID = WrongValue 的客户中删除

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

于 2011-03-08T19:08:19.360 回答
0

作为我评论的更新:

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

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

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

于 2011-03-08T19:15:28.253 回答