【问题标题】:Merging two tables with a common unique field in MySql在 MySql 中合并两个具有共同唯一字段的表
【发布时间】:2010-11-25 15:41:14
【问题描述】:

问题是:

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

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

两个表都是这样的

`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 的成员负载。我需要将它们合并在一起,保持成员 1 原样,并允许将来自成员 2 的唯一电子邮件插入成员 1。

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

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

【问题讨论】:

    标签: sql mysql merge


    【解决方案1】:

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

    1. 将来自 members2 的全新成员记录添加到 members1
    2. 更新 members1 中的电子邮件字段(如果 members2 中的更改)

    对于第一种情况,您应该可以执行以下操作:

    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:这两个语句都假设主键 'idmember' 在 members1 迁移期间没有更改!如果发生这种情况,这些查询将不起作用。)
    (注 3:如果您遇到 Note2 中的“不同 idmember 键”问题,您仍然可以使用查询,但将比较和连接操作更改为使用电子邮件字段。但是您必须先执行第二个查询以防止重复)

    【讨论】:

      【解决方案2】:

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

      首先,您应该检查 members2 中是否有任何行与 members1 中已存在的重复电子邮件地址:

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

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

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

      您可以将行从 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
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-31
          • 2021-07-15
          • 1970-01-01
          • 2010-11-14
          • 1970-01-01
          • 1970-01-01
          • 2017-08-05
          • 2013-11-26
          相关资源
          最近更新 更多