2017-10-04 26 views
1

我有一些表,我想获得每一行的哈希值(该列可以是任何日期类型)。每个表可能有不同的模式。以下是测试。将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

连接最多可处理32768个字符(max varchar2)。另外,我不确定你在问什么,但要清楚说明'ORA_HASH'不是'SHA1'哈希。如果你想要SHA1,你应该使用DBMS_CRYPTO;请参阅:https://stackoverflow.com/questions/1749753/making-a-sha1-hash-of-a-row-in-oracle – kfinity

+0

我想使用SHA1。但是,如果足够好,我可以使用ORA_hash。我将需要通过比较哈希代码来监视每日更改。 – ca9163d9

+0

ORA_HASH是一个32位散列函数,所以一旦你得到约9000个独特的行,你将有大约1%的碰撞几率。 SHA1是160位的,所以即使有数十亿行,你的碰撞几率也很小。所以是的,这取决于你的情况。 – kfinity

回答

1

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

如果你还在使用11g,你可以比较容易地复制函数,就像在我的回答here

  1. 确保NULL值产生的值,不取消所有的东西:

    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; 
    

    做这种排散列的时候有一些缺陷。

  2. 将列名称添加到散列。否则,值(1,2)可能会产生与(2,1)相同的散列。这在我上面的示例中不会发生,因为它按特定顺序连接字符串。但是,如果你正在哈希的事情有可能你最终想要一起添加散列,然后它可能会导致问题。
  3. 检查解决方案是否适用于不常见的数据类型。例如,ORA_HASH is not deterministic for CLOBS。我无法在STANDARD_HASH上找到任何信息,因此如果您的表格有不寻常的类型,请自行检查。
+0

谢谢,它的工作原理。我试过'standard_hash(a || b || c || x,'SHA1')',它似乎也在工作。它与你的相比如何? – ca9163d9

+0

@ ca9163d9该方法不会总是有效。想象一下,如果这些值是“(1 || null || 11)”和“(111 || null || null)”。它们是不同的值,但连接到相同的字符串。 –

+0

好的。那么'standard_hash('a'|| a ||'b'|| b ||'c'|| c ||'x'|| x,'SHA1')'?或者只是'standard_hash(','|| a ||','|| b ||','|| c ||','|| x,'SHA1')' – ca9163d9