如果问题是要检查两个表的身份,即答案为
是
- 表包含相同的数据或
否
- 存在差异,则有另一种方法,对于关系数据库来说不太常见,但对于文件来说是最先进的方法。
这与使用哈希代码检查已下载文件的“正确性”(即与原始文件的身份)相同。如果您看到相同的哈希代码,则答案是
是
,您拥有正确的文件。
如何将此方法转换为关系数据库?
Oracle提供了函数
standard_hash
,可为字符串计算
MD5
哈希代码。
select standard_hash('foo bar', 'MD5') hash_code from dual;
HASH_CODE
327B6F07435811239BC47E1544353273
因此,您可以比较列值。
函数
standard_hash
也适用于
CLOB
,因此(理论上)您可以连接列和行并计算整个表的哈希码。但这不是正确的方法,要记住文件的哈希码是通过组合行的哈希码来逐步计算的。
以下是演示如何使用Java类
java.security.MessageDigest
计算
MD5
哈希码的方法。我正在使用Groovy脚本,因为在PL/SQL中不可能实现。
MessageDigest digest = MessageDigest.getInstance("MD5")
byte[] md5hash
groovyCon.eachRow ('select txt from MY_TABLE order by id')
{
digest.update(it.txt.getBytes(StandardCharsets.UTF_8))
}
md5hash = digest.digest();
println md5hash.encodeHex().toString()
该脚本初始化哈希码,然后遍历行并更新哈希码,最后将其设置为字符串。这是在处理文件时的典型方法,其中行的顺序很重要。在关系表中,顺序未定义。您认为具有(A,B,C)和(C,B,A)的表是相同的。
请参见
此处讨论如何使用XOR以无序的方式组合哈希码。
以下是两个字符串哈希码组合的示例。
select UTL_RAW.BIT_XOR(standard_hash('foo', 'MD5'), standard_hash('bar', 'MD5')) hash_code from dual;
HASH_CODE
9B0805C206B7EBB8B6B9931D83E9F52A
这种方法有一个很大的优点,就是可以使用PL/SQL实现。在这里看一个实现PL/SQL
聚合函数 MD5_XOR
的例子,计算整个表的MD5哈希码。
select MD5_XOR(txt) hash_code, count(*) cnt
from MY_TABLE;
HASH_CODE CNT
173F1F8F85F1A154044B7629A23E949C 102
当然,您可以将参数连接起来以计算整个表的哈希码。
select MD5_XOR(to_char(id)||COL_TXT|| to_char(COL_DATE,'dd.mm.yyyy hh24:mi:ss')) md5 from MY_TABLE;
或者您可以使用
GROUP BY
将表的部分分组,以查看哪些组是相同的,哪些是不同的。
如果这个聚合函数被Oracle原生实现,性能将会非常好,比使用基于集合操作的SQL比较要好得多(需要对表进行排序)。
XOR
组合不需要排序,具有
O(N)
复杂度,但用户实现会受到上下文切换的影响。
请参见
这里的想法,使其成为Oracle本地实现。
inner join
仅比较city
列。其他列有何不同?如果有多个列被更新,你将如何加入? - Frank Ockenfuss