2

我正在开发一个基于数据输入流定期创建数据库记录的系统。偶尔会出现一些输入,证明两个独立创建的记录应该合并为一个。我正在寻找有关在数据库中实现合并的方法的建议。

主表(此时只是一个设计)包含由唯一 ID(称为主 ID,由数据库分配,我的系统中的 MySQL)和一些数据字段组成的记录。还有一些其他表使用主 ID 将其记录链接到主表中的记录。

MainTable:
int   mainID
blob  data
...

OtherTable:
int   otherID
int   mainID
blob  otherData
...

现在,如果从未将每条记录共享给任何外部进程或系统,则可以直接以某种方式将一条记录中的数据字段混合到另一条记录中并删除该记录的记录。将其他表中的主 ID 字段更新为我们保留的主 ID 值也很简单(如果乏味和/或效率低下)。

当每条记录的 ID 在系统外共享时,事情就会变得复杂。在这种情况下,我认为使用那些已删除的 ID 的查询完全失败应该是不合理的,尽管我可能会被说服。

我正在考虑的一个想法是引入一个包含两个关键字段的合并表:原始主 ID 和当前主 ID。其目的是将一个主 ID 别名为另一个主 ID。在创建每个主表记录时,我们向合并表添加一条记录,将新创建的主表记录的主 ID 映射到自身。如果发生合并,我们只需使用正在合并的主记录的原始主 ID 更新合并表中记录的当前主 ID 字段。然后,对于基于主 ID 的每个查询,我们通过合并表映射该 ID 以找到我们真正应该使用的有效主 ID。

MergeTable:
int   mergeID
int   originalMainID
int   currentMainID

这是一个很好的技术吗?映射能否在 SQL 查询中无缝完成?有没有我应该考虑的标准或更好的技术?

在对这个主题进行研究时,我发现很少有这样的例子。这个问题很接近,但合并场景与我的不同,或者在我看来是这样。我对数据库有所了解,但绝不是专家,所以我可能不知道要搜索的正确术语。

4

1 回答 1

3

我喜欢你的设计理念,但考虑一个你只在合并表中存储替换记录的地方,而不是全部。给定以下查询,这会减少存储并提高速度:

SELECT *
  FROM MainTable
  WHERE mainID = 1
UNION ALL
SELECT MainTable.*
  FROM MergeTable
  INNER JOIN MainTable
    ON MainTable.mainID = MergeTable.currentMainID
  WHERE MergeTable.originalMainID = 1
LIMIT 1

这个想法是,在大多数情况下,第一个查询将成功并返回一个结果,而 MySQL 将在满足 LIMIT 后中止第二个查询。如果第一个查询没有返回结果,那么它将继续进行第二个查询并在合并表上执行连接以查看它是否已合并。

根据 MySQL,关于 LIMIT:

一旦 MySQL 向客户端发送了所需数量的行,它就会中止查询,除非您使用 SQL_CALC_FOUND_ROWS。

如果合并的记录是例外,而不是规则,那么这将节省很多很多的连接。

如果 UNION 查询太吓人,您也可以使用两个查询来执行此操作。您可以简单地检查记录是否存在,如果不存在,则检查合并表。

于 2012-05-23T22:00:45.690 回答