Sql 合并数据库如何处理重复的PK';s

Sql 合并数据库如何处理重复的PK';s,sql,database,merge,Sql,Database,Merge,我们有三个数据库,它们在物理上按地区分开,一个在洛杉矶、旧金山和纽约。所有数据库共享相同的模式,但包含特定于其区域的数据。我们希望将这些数据库合并为一个数据库,并对其进行镜像。我们需要保留每个区域的数据,但将它们合并到一个db中。这给我们带来了很多问题,例如,我们肯定会有重复的主键,而外键可能无效 我希望能找到一个有过类似工作经验的人,他能提供一些技巧、策略和经验,告诉我们如何完成合并 例如,一个想法是创建复合键,然后更改代码和存储过程,通过复合键(区域/原始pk)查找数据。但这需要我们更改所有

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

我希望能找到一个有过类似工作经验的人,他能提供一些技巧、策略和经验,告诉我们如何完成合并

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

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


欢迎有任何经验

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

以下是有关GUID的一些信息:

也许SQLServerManagementStudio允许您轻松地将列转换为使用GUID。我希望如此


祝你好运。

我没有这方面的第一手经验,但在我看来,你应该能够为每个服务器唯一地映射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,但通过这种方式构造它,您可以轻松地更新FKs(假设每个服务器上的数据都是隔离的,就像我所做的那样)。祝你好运。

最好:为RegionCode添加一列,并将其包含在PKs中,但你不想做所有的腿部工作

HACK:如果您的ID是INT,一个快速修复方法是在导入时根据区域为每个键添加一个固定值。整数可以大到:2147483647

本地服务器数据:

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
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
将100000000添加到LA的ID中
将200000000添加到SF的ID中
将300000000添加到纽约的ID

组合服务器数据:

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
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

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

  • 创建具有相同架构的新数据库 但是只有桌子。无pk fk,检查 等等
  • 将数据从DB1传输到此数据库 源数据库
  • 对于目标数据库中的每个表 查找PK的顶部编号
  • 对于源中的每个表 数据库更新其pk、fk等 从(最上面的数字+1)开始 从目标数据库
  • 对于目标数据库中的每个表 将标识插入设置为on
  • 将数据从源数据库导入目标数据库 分贝
  • 对于目标数据库中的每个表 将“标识插入”设置为“关闭”
  • 清除源数据库
  • 对DB2重复上述步骤

  • 正如Jon提到的,我将使用GUI来解决合并任务。我看到两种不同的解决方案需要GUI:

    1) 永久更改数据库架构,以使用GUID而不是整数(标识)作为主键。 一般来说,这是一个很好的解决方案,但是如果您有很多非SQL代码以某种方式绑定到标识符的工作方式,那么可能需要对代码进行一些更改。可能因为您合并了数据库,所以您可能无论如何都需要更新您的应用程序,以便它仅根据登录的用户等使用一个区域的数据

    2) 临时添加仅用于迁移目的的GUID,迁移数据后,将其删除: 这是一个比较棘手的问题,但是一旦您编写了这个迁移脚本,您就可以(重新)多次运行它来再次合并数据库,以防第一次出错。以下是一个例子:

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

    然后将FKs更新为与整数一致:

    --// 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约束

    现在将从每个源数据库插入到目标数据库(注意:我们不插入PKs和整数FKs):

    插入所有数据库中的数据后,运行与原始数据库相反的代码,以使整数FKs与目标数据库上的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 ALTER TABLE ADDROP列UID ALTER TABLE ADDRESS DROP列PERSON\u UID

    因此,在最后,您应该得到一个相当长的迁移脚本,它应该可以为您完成这项工作。重点是-这是可行的


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

    我已经做了,我说的是更改键(选择方法),而不是更改代码。您总是会错过存储过程或引入错误。有了数据更改,编写测试以查找孤立记录或验证内容是否正确匹配非常容易。对于代码更改,尤其是工作正常的代码,很容易遗漏一些内容。

    我没有解决方案,但这是一个最好的例子,当GUID/UniqueIdentifier作为主键是件好事时。;)当然同意,西蒙!不幸的是,这个数据库模型早在我开始这个项目之前就已经存在了。时间机器肯定会来
    --// set ADDRESS.PERSON_ID
    UPDATE  ADDRESS
    SET     ADDRESS.PERSON_ID = PERSON.ID
    FROM    ADDRESS
    INNER JOIN PERSON
        ON  ADDRESS.PERSON_UID = PERSON.UID