我正在开发一个系统,根据输入的数据流定期创建数据库记录。偶尔会出现一些输入,提供两个独立创建的记录应合并为一个的证据。我正在寻找有关如何在数据库中实现合并的建议。
主表(此时仅为设计)包含由唯一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。
MergeTable:
int mergeID
int originalMainID
int currentMainID
这是一项好技术吗?映射可以在SQL查询中无缝完成吗?是否有我应该考虑的标准或更好的技术?
在对这个主题进行研究时,我发现很少有例子。 This question很接近,但合并场景与我的不同,或者在我看来。我对数据库有点了解,但绝不是专家,所以我可能不知道要搜索的正确术语。
答案 0 :(得分:2)
我喜欢你的设计理念,但考虑一下你只在合并表中存储被替换的记录,而不是全部。考虑到以下查询,这会减少存储并提高速度:
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查询太可怕,您也可以使用两个查询执行此操作。您只需检查记录是否存在,如果不存在,则检查合并表。