2017-10-04 13 views
1

私はいくつかのテーブルを持っており、すべての行のハッシュ値を取得したい(このカラムは任意の日付タイプにすることができます)。各表は異なるスキーマを持つことがあります。以下はテストのためのものです。 get_sha1_hashを実装する方法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 

?次は十分ですか?

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

最大32768文字(最大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ビットのハッシュ関数なので、〜9,000の一意の行を取得すると、衝突確率は約1%になります。 SHA1は160ビットなので、何十億行もある場合でも、衝突の可能性は非常に低くなります。だから、それはあなたの状況によって異なります。 – kfinity

答えて

1

12cでネストされたSTANDARD_HASH関数を使用してください。これはSHA1をサポートしています。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に関する情報を見つけることができませんので、あなたのテーブルに異常なタイプがある場合は、これを自分で確認してください。
+0

ありがとう、それは動作します。私は 'standard_hash(a || b || c || x、 'SHA1')'を試しました。それはあなたのものとどのように比較されますか? – ca9163d9

+0

@ ca9163d9その方法は必ずしも機能しません。値が '(1 || null || 11)'と '(111 || null || null)の場合を想像してください。それらは異なる値ですが、同じ文字列に連結されます。 –

+0

良いキャッチ。標準的なハッシュ( 'a' || a || 'b' || b || 'c' || c || 'x' || x、 'SHA1') 'または単に 'standard_hash( '、' || a || '、' || b || '、' || c || '、' || x、 'SHA1')' – ca9163d9

関連する問題