【问题标题】:Merging databases how to handle duplicate PK's合并数据库如何处理重复的 PK
【发布时间】:2010-11-08 19:29:02
【问题描述】:

我们有三个数据库,它们按地区在物理上分开,一个位于洛杉矶、旧金山和纽约。所有数据库共享相同的模式,但包含特定于其区域的数据。我们希望将这些数据库合并为一个并进行镜像。我们需要保留每个区域的数据,但将它们合并到一个数据库中。这给我们带来了很多问题,例如我们肯定会有重复的主键,而外键可能会无效。

我希望找到有过类似任务经验的人,他可以就我们如何完成合并提供一些提示、策略和经验词。

例如,一个想法是创建复合键,然后更改我们的代码和存储过程以通过复合键(区域/原始 pk)查找数据。但这需要我们更改所有代码和存储过程。

另一个想法是只导入数据并让它生成新的 PK,然后将所有 FK 引用更新到新的 PK。这样我们就不必更改任何代码。

欢迎任何经验!

【问题讨论】:

  • 我没有解决方案,但这是一个很好的例子,当有 guids/uniqueidentifiers 作为主键是一件好事。 ;)
  • 当然同意西蒙!不幸的是,这个数据库模型早在我开始从事这个项目之前就已经存在了。时间机器肯定会派上用场! :)

标签: sql database merge


【解决方案1】:

我已经这样做了,我说更改您的密钥(选择一种方法)而不是更改您的代码。您总是会错过存储过程或引入错误。随着数据的变化,很容易编写测试来查找孤立记录或验证事情是否正确匹配。随着代码的更改,尤其是正常工作的代码,很容易错过一些东西。

【讨论】:

    【解决方案2】:

    正如 Jon 所提到的,我会使用 GUID 来解决合并任务。而且我看到了两种需要 GUID 的不同解决方案:

    1) 永久更改您的数据库架构以使用 GUID 而不是 INTEGER (IDENTITY) 作为主键。

    一般来说这是一个很好的解决方案,但是如果您有很多非 SQL 代码以某种方式绑定到您的标识符的工作方式,则可能需要进行相当多的代码更改。 可能由于您合并数据库,您可能无论如何都需要更新您的应用程序,以便它仅根据登录用户等处理一个区域数据。

    2) 临时添加 GUID 仅用于迁移目的,数据迁移后删除:

    这个有点棘手,但是一旦你编写了这个迁移脚本,你可以(重新)多次运行它来再次合并数据库,以防你第一次搞砸了。这是一个例子:

    Table: PERSON (ID INT PRIMARY KEY, Name VARCHAR(100) NOT NULL)
    Table: ADDRESS (ID INT PRIMARY KEY, City VARCHAR(100) NOT NULL, PERSON_ID INT)
    

    您的更改脚本是(请注意,对于所有 PK,我们会自动生成 GUID):

    ALTER TABLE PERSON ADD UID UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID())
    ALTER TABLE ADDRESS ADD UID UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID())
    ALTER TABLE ADDRESS ADD PERSON_UID UNIQUEIDENTIFIER NULL
    

    然后您将 FK 更新为与 INTEGER 一致:

    --// set ADDRESS.PERSON_UID
    UPDATE  ADDRESS
    SET     ADDRESS.PERSON_UID = PERSON.UID
    FROM    ADDRESS
    INNER JOIN PERSON
        ON  ADDRESS.PERSON_ID = PERSON.ID
    

    您为所有 PK(自动生成 GUID)和 FK(如上所示更新)执行此操作。

    现在您创建目标数据库。在此目标数据库中,您还可以为所有 PK 和 FK 添加 UID 列。同时禁用所有 FK 约束。

    现在您从每个源数据库插入目标数据库(注意:我们不插入 PK 和整数 FK):

    INSERT INTO TARGET_DB.dbo.PERSON (UID, NAME)
    SELECT UID, NAME FROM SOURCE_DB1.dbo.PERSON
    
    INSERT INTO TARGET_DB.dbo.ADDRESS (UID, CITY, PERSON_UID)
    SELECT UID, CITY, PERSON_UID FROM SOURCE_DB1.dbo.ADDRESS
    

    从所有数据库中插入数据后,运行与原始代码相反的代码以使整数 FK 与目标数据库上的 GUID 一致:

    --// set ADDRESS.PERSON_ID
    UPDATE  ADDRESS
    SET     ADDRESS.PERSON_ID = PERSON.ID
    FROM    ADDRESS
    INNER JOIN PERSON
        ON  ADDRESS.PERSON_UID = PERSON.UID
    

    现在您可以删除所有 UID 列: ALTER TABLE PERSON DROP 列 UID 更改表地址删除列 UID ALTER TABLE ADDRESS DROP COLUMN PERSON_UID

    所以最后你应该得到一个相当长的迁移脚本,它应该可以为你完成这项工作。关键是 - 这是可行的

    注意:这里写的都没有经过测试。

    【讨论】:

    • 基本上最大的问题是表之间的关系,答案中的workflow显示了如何解决它。祝你好运!
    【解决方案3】:

    我在这种情况下所做的是这样的:

    1. 创建一个具有相同架构的新数据库 但只有桌子。没有pk fk,检查 等
    2. 将数据从 DB1 传输到此 源数据库
    3. 针对目标数据库中的每个表 查找 PK 的最高数字
    4. 对于源中的每个表 数据库更新他们的pk、fk等 从(顶部数字 + 1)开始 从目标数据库
    5. 针对目标数据库中的每个表 将身份插入设置为开启
    6. 从源数据库导入数据到目标 分贝
    7. 针对目标数据库中的每个表 将身份插入设置为关闭
    8. 清除源数据库
    9. 为 DB2 重复

    【讨论】:

      【解决方案4】:

      最佳:为 RegionCode 添加一列,并将其包含在您的 PK 中,但您不想做所有的工作。

      HACK:如果您的 ID 是 INT,快速解决方法是在导入时为每个键添加基于区域的固定值。 INT 可以大到:2,147,483,647

      本地服务器数据:

      LA IDs: 1,2,3,4,5,6
      SF IDs: 1,2,3,4,5
      NY IDs: 1,2,3,4,5,6,7,9
      

      将 100000000 添加到 LA 的 ID
      将 200000000 添加到 SF 的 ID
      将 300000000 添加到 NY 的 ID

      合并的服务器数据:

      LA IDs: 100000001,100000002,100000003,100000004,100000005,100000006
      SF IDs: 200000001,200000002,200000003,200000004,200000005
      NY IDs: 300000001,300000002,300000003,300000004,300000005,300000006,300000007,300000009
      

      【讨论】:

        【解决方案5】:

        我没有这方面的第一手经验,但在我看来,你应该能够为每个服务器唯一地映射 PK -> 新 PK。例如,生成新的 PK,使得来自 LA 服务器的数据具有 PK % 3 == 2,SF 具有 PK % 3 == 1,而 NY 具有 PK % 3 == 0。因为,无论如何,正如我理解你的问题,每个服务器只存储与其自身数据的 FK 关系,您可以以相同的方式更新 FK。

        NewLA = OldLA*3-1
        NewSF = OldLA*3-2
        NewNY = OldLA*3
        

        然后您可以合并它们并且没有重复的 PK。正如您已经说过的,这本质上只是生成新的 PK,但是以这种方式构建它可以让您轻松更新 FK(假设,正如我所做的那样,每个服务器上的数据都是隔离的)。祝你好运。

        【讨论】:

          【解决方案6】:

          您可以做的一件事是使用区域数据设置表格以使用 GUID。这样,每个区域的主键都是唯一的,您可以混合和匹配数据(将数据从一个区域导入到另一个区域)。对于具有共享数据的表(如类型表),您可以保持主键不变(因为它们应该在任何地方都相同)。

          以下是有关 GUID 的一些信息: http://www.sqlteam.com/article/uniqueidentifier-vs-identity

          也许 SQL Server Management Studio 可以让您轻松转换列以使用 GUID。我希望如此!

          祝你好运。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-09-17
            • 1970-01-01
            • 1970-01-01
            • 2011-05-24
            • 2018-10-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多