在MySql中合并两个具有公共唯一字段的表

时间:2009-09-04 14:01:00

标签: sql mysql merge

问题是:

我们已经接管了一个拥有活跃会员社区的网站。我们已经获得了应用程序和数据库转储,并且已成功在新服务器上运行该站点并且已切换DNS。

问题是数据库在将文件发送给我们并切换DNS所花费的时间内已经不同步了。现在DNS已经切换并且数据库不可能不同步,我们已经交给了member2,这是来自原始服务器的表,带有额外的数据。

两个表都是这样的

`idmembers` int(10) unsigned NOT NULL auto_increment,
`firstName` varchar(20) default NOT NULL,
`lastName` varchar(20) default NOT NULL,
`email` varchar(255) default NOT NULL,
`date` varchar(10) default '0',
`source` varchar(50) default 'signup'
 PRIMARY KEY  (`idmembers`),
 UNIQUE KEY `email` (`email`)

因此,第一个表称为members1,是实时数据库,缺少来自members2的成员。我需要将它们合并在一起,保持member1不变,并允许members2的唯一电子邮件插入members1。

我假设有一些SQL可以做到这一点,但我不知道它可能是什么。

我的第二个也是不太可取的方法是使用像PhpMyAdmin这样的工具在某个日期之后导出members2中的所有记录并将它们重新导入到members1中,但问题是它们都是从member2导出的,其中idmembers与members1冲突(作为自动增量用于两者)

3 个答案:

答案 0 :(得分:2)

如果我理解你的问题,这里有两个不同的问题:

  1. 将member2中的全新成员记录添加到members1
  2. 更新members1中的电子邮件字段(如果在members2中已更改
  3. 至于第一种情况,您应该可以执行以下操作:

    INSERT INTO members1 ('idmembers', 'firstname', etc.)
     SELECT 'idmembers', 'firstname', etc.
      FROM members2
      WHERE idmembers NOT IN (SELECT idmembers FROM members1)
    

    至于第二种情况,例如:

    UPDATE members1 m1 LEFT JOIN members2 m2
     ON m1.idmembers = m2.idmembers
     SET m1.idmembers = m2.idmembers
     WHERE m2.idmembers IS NOT NULL AND m2.idmembers != m1.idmembers
    

    (注1:这两个陈述都是'临时'和未经测试的!) (注2:两个语句都假定在成员1迁移期间主键'idmember'没有改变!如果发生这种情况,这些查询将无效。)
    (注3:如果您在Note2中遇到“不同的idmember密钥”问题,您仍然可以使用查询,但更改比较和连接操作以使用电子邮件字段。但是您必须先执行第二个查询以防止重复)

答案 1 :(得分:1)

最重要的建议是在数据库的副本而不是实时数据库上执行此操作,直到您确定该过程会导致更正合并!

首先,您应检查member2中是否有任何行,其成员1中已存在重复的电子邮件地址:

SELECT members2.*
FROM members1 JOIN members2 USING (email);

如果有(希望它会很少),请手动修复它们,或者删除每一行,这些行实际上是已经在members1中拥有帐户的人的重复帐户(当然要保留备份数据)。 / p>

如果冗余成员帐户的任何其他情况应被视为重复,并且未作为新成员插入,则可能必须手动处理。这是数据库清理重复数据删除这个通常无法完全自动化的更广泛问题的示例。

您可以将members2中的行复制到members1中,同时生成如下所示的新ID值:

INSERT INTO members1 (`firstName`, `lastName`, `email`, `date`, `source`)
  SELECT `firstName`, `lastName`, `email`, `date`, `source`
  FROM members2;

是的,您必须为所有列命名。通过从该查询中省略idmembers,该列将使用其默认行为来生成新的id值。

您没有说您需要更新通过其ID引用这些新成员的其他表。如果是这样,您应该创建一个新表来将members2 id映射到将它们导入members1时生成的新数字。您必须遵循@ ijclarkson的建议,即一次插入一个成员,这样您就可以注意到生成的新ID。

SELECT * FROM members2;

-- loop over results in a script:

  INSERT INTO members1 (`firstName`, `lastName`, `email`, `date`, `source`)
    VALUES (?, ?, ?, ?, ?);

  INSERT INTO members_id_map (idmembers1, idmembers2)
    VALUES (LAST_INSERT_ID(), ?); -- use idmembers from the query on members2

-- end loop

答案 2 :(得分:0)

只需编写一个快速移植脚本,选择“members1”中缺少的字段,然后对“members2”表中的每个字段执行INSERT。

如果您需要唯一的电子邮件地址,可能需要进行一些检查,并且您认为可能存在重复项。