【问题标题】:How to merge two identical database data to one?如何将两个相同的数据库数据合并为一个?
【发布时间】:2013-02-23 15:11:58
【问题描述】:

两个客户将合并。他们都在使用我的应用程序,以及他们自己的数据库。大约几周后,他们正在合并(他们成为一个组织)。所以他们希望将所有数据都放在一个数据库中。

所以这两个数据库结构是相同的。问题出在数据上。例如,我有桌子位置和人员(这只是两张 50 人的桌子):

数据库 1:

Locations:

Id    Name         Adress   etc....
1     Location 1
2     Location 2

Persons:

Id    LocationId     Name     etc...
1     1              Alex
2     1              Peter
3     2              Lisa

数据库 2:

Locations:

Id    Name         Adress   etc....
1     Location A
2     Location B

Persons:

Id    LocationId     Name     etc...
1     1              Mark
2     2              Ashley
3     1              Ben

我们看到该人与位置相关(locationId 列)。请注意,我有更多表是指位置表和人员表。

数据库包含自己的位置和人员,但 ID 可以相同。以防万一,当我想将所有内容导入 DB2 时,应将 DB1 的位置插入到 ID 为 3 和 4 的 DB2 中。来自 DB1 的人员应具有新的 ID 4、5、6 以及人员表中的位置必须更改为 ids 4,5,6。

我对这个问题的解决方案是编写一个处理所有事情的查询,但我不知道从哪里开始。

什么是最好的方法(在查询中)重新编号的 Id 字段也对孩子有级联?数据库不包含参照完整性和外键(外键未在数据库中定义)。创建 FKey 和级联不是一种选择。

我使用的是 sql server 2005。

【问题讨论】:

  • 您可以有另一个字段,即“实际”ID。但是,这可能会产生它自己的一系列问题。另外,写一个大查询是要走的路吗?您可能只需要编写一个存储过程来执行此操作
  • 也可以为eacht表写1个sp。然后你会有更多的结构。问题是没有查询或存储过程,两者都可以。

标签: sql sql-server sql-server-2005 stored-procedures


【解决方案1】:

您说两个客户都在使用您的应用程序,所以我假设它是某种“收缩包装”软件,被更多客户使用,而不仅仅是这两个,对吗?

如果是,向表中添加特殊列或类似的操作可能会在未来造成麻烦,因为您要么必须为这两个客户维护一个可以处理额外列的特殊版本。或者您必须将这些列引入您的主代码库,这意味着您的所有其他客户也会获得它们。

我可以想到一种更简单的方法来执行此操作,而无需更改任何表格或添加任何列。
为了使其工作,您需要找出两个数据库中同时存在的最大 ID(无论它在哪个表或哪个数据库中)

这可能需要一些复制和粘贴来获得大量如下所示的查询:

select max(id) as maxlocationid from locations
select max(id) as maxpersonid from persons
-- and so on... (one query for each table)

当您在两个数据库中运行查询后找到最大的 ID 时,取一个大于该 ID 的数字,并将其添加到第二个数据库中所有表中的所有 ID。
该数字必须大于两个数据库中已经存在的最大 ID,这一点非常重要!

有点难解释,这里举个例子:

假设两个数据库中任何表的最大 ID 是 8000
然后运行一些 SQL 将10000 添加到第二个数据库中每个表的每个 ID:

update Locations set Id = Id + 10000
update Persons set Id = Id + 10000, LocationId = LocationId + 10000
-- and so on, for each table

查询相对简单,但这是最有效的,因为您必须为数据库中的每个表手动构建这样的查询,并使用所有 ID 列的正确名称。

在第二个数据库上运行查询后,您问题中的示例数据将如下所示:

数据库 1: (和之前一模一样)

Locations:

Id    Name         Adress   etc....
1     Location 1
2     Location 2

Persons:

Id    LocationId     Name     etc...
1     1              Alex
2     1              Peter
3     2              Lisa

数据库 2:

Locations:

Id    Name         Adress   etc....
10001 Location A
10002 Location B

Persons:

Id    LocationId     Name     etc...
10001 10001          Mark
10002 10002          Ashley
10003 10001          Ben

就是这样!现在您可以将数据从一个数据库导入另一个数据库,而不会出现任何主键违规。

【讨论】:

  • 非常感谢。你的例子很清楚。我只是害怕一个非常大的整数。一个 int 可以有 max = 999999999。有没有办法避免这种情况?
  • 不,the maximum number for an int is 2,147,483,647。你的表中真的有那么多行吗?但是当我阅读链接的 MSDN 页面时,我想到了另一个想法:int 的 minimum 值为 -2,147,483,647。因此,您可以在一个数据库中将所有 ID 与 -1 相乘,只要您的应用不介意小于零的 ID。
  • 实际上,我希望 4 - 7 个表有这么多行。其他表不会有问题。你对这个表有什么建议(-1 数字除外)?
  • 首先,看看这4-7个表,看看它们的ID是不是真的那么大。
  • “乘以负数”是一个很好的“技巧”。但请确保您的代码正在检查 !=0 而不是 >0 (对于在数据库中找到的实体)。 (我的经验是,人们会检查 SurrogateKey 的值是否不等于零作为“它存在”检查)。
【解决方案2】:

如果这是我的问题,我可能会在我要保留的数据库中的表中添加一些列。这些将用于存储来自其他数据库的 pk 值。然后我会从其他表中插入记录。对于那些有外键的,我会使用一个已知的值。然后我会根据需要更新并删除我添加的列。

【讨论】:

  • 首先,在目标数据库中引入包含原始键的新列?在内存中做所有事情(比如临时表或声明表)是个好主意吗?
  • 我的回答是基于您的 pk 值是由您的数据库以某种方式自动生成的假设。在某些时候,这必须发生在您的新记录中。我没有看到使用临时表有什么贡献。
猜你喜欢
  • 2014-02-24
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-30
  • 1970-01-01
  • 2012-09-09
相关资源
最近更新 更多