将字符串散列为PostgreSQL中的数值

时间:2012-03-21 17:03:44

标签: postgresql plpgsql postgresql-8.4

我需要将存储在我的数据库中的字符串转换为数字值。结果可以是Integer(首选)或Bigint。此转换将在PL / pgSQL函数的数据库端完成。

有人可以指点一些算法或任何可用于实现此目的的API吗?

我一直在Google上搜索这几个小时,到目前为止找不到任何有用的东西:(

4 个答案:

答案 0 :(得分:40)

保留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;

答案 1 :(得分:13)

您可以毫无问题地创建md5哈希值:

select md5('hello, world');

返回一个十六进制数的字符串。

不幸的是,没有内置函数可以将十六进制转换为整数,但是无论如何你都是在PL / pgSQL中这样做,这可能会有所帮助:

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

答案 2 :(得分:4)

必须是整数吗? 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

答案 3 :(得分:0)

这是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;