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

slmsl1lt  于 2023-06-22  发布在  Oracle
关注(0)|答案(2)|浏览(228)

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

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
fnatzsnv

fnatzsnv1#

在12 c中使用嵌套的STANDARD_HASH函数。它支持SHA1,正如@kfinity所解释的那样,它不太可能产生冲突,也不会溢出字符限制。(除非你有一个荒谬的列数,在这种情况下,你可以把函数分成多个部分,然后再次哈希。
如果你还在使用11 g,你可以相对容易地复制我的答案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产生一个值,并且不会抵消所有的值。
1.将列名添加到哈希。否则,值(1,2)可以产生与(2,1)相同的散列。在我上面的例子中不会发生这种情况,因为它是以特定的顺序连接字符串。但是如果你是散列的话,你最终可能会想把散列加在一起,这样就可能会产生问题。
1.检查解决方案是否适用于不寻常的数据类型。例如,ORA_HASH is not deterministic for CLOBS。我找不到任何关于STANDARD_HASH的信息,所以如果你的表有不寻常的类型,请自己检查。

zfycwa2u

zfycwa2u2#

至少在Oracle 19中,这似乎也能可靠地工作,而且比@ Jon-Heller的优秀答案更容易使用:

WITH values1 AS
(
  SELECT
    null, 1
  FROM
    dual
  UNION 
  SELECT
    1, null
  FROM
    dual
), values2 AS
(
SELECT
  null, '1'
FROM
  dual
UNION 
SELECT
  '1', null
FROM
  dual
)

SELECT
  rawtohex(standard_hash(json_object(*))) AS hashed
FROM
  values1
UNION ALL
SELECT
  rawtohex(standard_hash(json_object(*)))
FROM
  values2

产量
| 散列|
| - -----|
| 34BF2884FD8EE260AEE479600DE7CA27E4AABEDA|
| 5C91114F78949FDEEC84BCD5FBE4057570CD5149|
| DF54D6C3FD95C4FC3EA274DF50CE22AF28972F04|
| BD5DB32944879E000D14396CF028DDB44C70687F|
或者使用原始示例:

SELECT
  rawtohex(standard_hash(json_object(*))) AS hashed
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;

| 散列|
| - -----|
| 4F7C93B5F106D7E93CD43047F39EA3503509C22A|
| B6565A1184308B13ACC1E543D3BD573B4D845958|
| A86E32443F2D81E454151CBFCF64B0D67C7F8C0B|
| 3A522C3EE28B8D62CD3278D509FD6D4B7DF433B3|
| 83299BB84F4FBB28B0F146DA579A831F6DA5C426|

相关问题