web-dev-qa-db-ja.com

PostgreSQLで文字列を数値にハッシュする

データベースに保存されている文字列を数値に変換する必要があります。結果は、整数(推奨)またはBigintになります。この変換は、PL/pgSQL関数のデータベース側で行われます。

誰かが私にいくつかのアルゴリズムまたはこれを達成するために使用できるAPIを教えてもらえますか?

私はこれを何時間もGoogleで検索してきましたが、これまでに役立つものは見つかりませんでした:(

33
Salman A. Kagzi

MD5ハッシュの最初の32ビットまたは64ビットを保持するだけです。もちろん、それはmd5のメインプロパティ(=衝突の確率が無限小)を無効にしますが、おそらく問題に十分な値の広い分散が得られます。

他の回答から派生したSQL関数:

Bigintの場合:

create function h_bigint(text) returns bigint as $$
 select ('x'||substr(md5($1),1,16))::bit(64)::bigint;
$$ language sql;

Intの場合:

create function h_int(text) returns int as $$
 select ('x'||substr(md5($1),1,8))::bit(32)::int;
$$ language sql;
41
Daniel Vérité

問題なくmd5ハッシュ値を作成できます。

select md5('hello, world');

これは、16進数の文字列を返します。

残念ながら、16進数を整数に変換する組み込み関数はありませんが、とにかくPL/pgSQLでそうしているので、これが役立つ場合があります。

https://stackoverflow.com/a/8316731/330315

14

整数でなければなりませんか? pg_crypto モジュールは、いくつかの標準ハッシュ関数(md5、sha1など)を提供します。彼らはすべてbyteaを返します。いくつかのビットを捨てて、byteaを整数に変換できると思います。

bigintは小さすぎて暗号ハッシュを格納できません。 Pgがサポートする最大の非byteaバイナリ型はuuidです。次のようにダイジェストをuuidにキャストできます。

select ('{'||encode( substring(digest('foobar','sha256') from 1 for 16), 'hex')||'}')::uuid;
                 uuid                 
--------------------------------------
 c3ab8ff1-3720-e8ad-9047-dd39466b3c89
4
dbenhur

これは、JavaのString.hashCode()の実装です。

CREATE OR REPLACE FUNCTION hashCode(_string text) RETURNS INTEGER AS $$
DECLARE
  val_ CHAR[];
  h_ INTEGER := 0;
  ascii_ INTEGER;
  c_ char;
BEGIN
  val_ = regexp_split_to_array(_string, '');

  FOR i in 1 .. array_length(val_, 1)
  LOOP
    c_ := (val_)[i];
    ascii_ := ascii(c_);
    h_ = 31 * h_ + ascii_;
    raise info '%: % = %', i, c_, h_;
  END LOOP;
RETURN h_;
END;
$$ LANGUAGE plpgsql;
0
dvlcube