将Oracle行序列化为字符串并获取其哈希值?

时间:2017-10-04 19:14:04

标签: oracle

我有一些表,我想得到每一行的哈希值(该列可以是任何日期类型)。每个表可能具有不同的架构。以下是测试。

select *, 
       get_sha1_hash(a, b, c, x) Hash -- Get the Sha1 hash of columns a, b, c, x
from (
    select 1 a, 2 b, 3.1 c, 'aa' x from dual union all
    select 4 a, 5 b, 6.3 c, 'bb' from dual union all
    select 1 a, 2 b, 9.9 c, 'cc' from dual ) t

如何实施get_sha1_hash?以下是否足够好?

select ora_hash(a || b || c || x) from t

1 个答案:

答案 0 :(得分:1)

在12c中使用嵌套的STANDARD_HASH函数。它支持SHA1,正如@kfinity所解释的那样,它不太可能产生冲突,也不会溢出字符限制。 (除非你有一个荒谬的列数,在这种情况下你可以将函数分成多个部分并再次哈希。)

如果你仍在使用11g,你可以比我的回答here更容易地复制这个功能。

select t.*,
    standard_hash
    (
        standard_hash(a, 'SHA1')||'a'||
        standard_hash(b, 'SHA1')||'b'||
        standard_hash(c, 'SHA1')||'c'||
        standard_hash(x, 'SHA1')||'x'
        , 'SHA1'
    ) hash
from
(
    select 1 a, 2 b, 3.1 c, 'aa' x from dual union all
    select 4 a, 5 b, 6.3 c, 'bb' x from dual union all
    select 1 a, 2 b, 9.9 c, 'cc' x from dual union all
    --Test with NULL and with flipping column values.
    select 1 a, 2 b, 9.9 c, null x from dual union all
    select 2 a, 1 b, 9.9 c, 'cc' x from dual
) t;

进行这种行散列时有一些陷阱:

  1. 确保NULL生成一个值,并且不要取消所有内容。
  2. 将列名添加到哈希。否则,值(1,2)可以产生与(2,1)相同的散列。这不会发生在上面的示例中,因为它以特定顺序连接字符串。但是如果你正在散列东西,那么你最终可能会想要将哈希值加在一起,然后就会出现问题。
  3. 检查解决方案是否适用于异常数据类型。例如,ORA_HASH is not deterministic for CLOBS。我找不到有关STANDARD_HASH的任何信息,因此如果您的表格有异常类型,请自行检查。