8

我想每个人都会偶尔遇到这个问题:您有两个表,它们的主键自动编号需要合并。使用自动编号主键来支持应用程序生成的键的原因有很多,但与其他表合并肯定是最大的缺点之一。

出现的一些问题是重叠的 id 和不同步的外键。我想听听你解决这个问题的方法。我总是遇到问题,所以我很好奇是否有人有某种通用解决方案。

- 编辑 -

针对建议使用 guid 或其他非数字键的答案,在某些情况下,提前使用自动编号键似乎是一个更好的主意(稍后您会后悔),或者您正在接管其他人的项目,或者你得到一些你必须使用的遗留数据库。所以我真的在寻找一个你不再控制数据库设计的解决方案。

4

5 回答 5

4

解决方案包括:

  • 使用 GUID 作为主键而不是更简单的标识字段。很可能避免重叠,但 GUID 更难使用并且不能很好地与聚集索引一起使用。

  • 将主键设为多列键,第二列通过识别合并数据的来源来解决重叠值。可移植,与聚集索引一起使用效果更好,但开发人员讨厌多列键。

  • 使用自然键而不是伪键。

  • 为合并的表之一分配新的主键值,并将这些更改级联到任何相关行。这会将合并操作更改为 ETL 操作。如果您无法更改数据库设计,这是您可以用于遗留数据的唯一解决方案。

我不确定是否有一种万能的解决方案。根据情况选择其中之一。

于 2010-09-29T18:30:12.830 回答
3

嗯,我对我刚刚在 AlexKuznetsov 的回答中发表评论的想法有点热情,所以我会对此做出一个完整的回答。

考虑将表命名为 table1 和 table2,其中 id1 和 id2 作为自动编号主键。它们将使用 id3(非自动编号主键)合并到 table3。

为什么不:

  1. 删除 table1 和 table2 的所有外键约束
  2. 对于所有引用 table1 的外键字段,执行一个UPDATE table SET id1 = id1 * 2,对于引用 table2 的 FK 字段,执行一个UPDATE table SET id2 = (id2) * 2 + 1
  3. 通过执行一个填充 table3INSERT INTO table3 SELECT id1 * 2 AS id3, ... FROM table1 UNION ALL SELECT id2 * 2 + 1 AS id3 FROM table2
  4. 为 table3 创建新的外键约束

它甚至可以与 3 个或更多表一起使用,只需使用更高的乘数。

于 2010-09-29T21:03:10.927 回答
1

为这种可能性设计的一种标准方法(如果不是标准方法)是将 GUID 用于主键而不是整数 - 合并相对容易,因为保证不会遇到重叠。

除非重新设计,否则我认为您不得不插入表中,接受您将获得新的主键,并确保您维护从旧 ID 到新 ID 的映射 - 然后插入引用数据使用 FK 重新映射等。如果您的数据有一个“业务密钥”在插入后将保持唯一,这将节省必须跟踪映射。

于 2010-09-29T18:30:44.837 回答
1

我确定你只有两个这样的表,你可以在一个表中只有偶数 ID (0,2,4,6,...),而在另一个表 (1,3,5,7,...) 中有奇数 ID )

于 2010-09-29T18:33:19.200 回答
1

假设您在要合并的表中也有一个自然键,那么这个过程并不困难。自然键用于重复数据删除和正确重新分配任何引用。您可以随时重新编号代理键值 - 这是首先使用代理的主要优势之一。

所以我不认为这是代理键的问题 - 只要您始终强制执行自然键(实际上我更喜欢术语“业务键”)。如果您没有这些表的业务密钥,那么现在可能是重新设计的好时机,以便正确实施所有必要的密钥。

于 2010-09-29T19:13:03.643 回答