我需要将存储在数据库中的字符串转换为数值。结果可以是Integer(首选)或Bigint。这个转换将在PL/pgSQL函数的数据库端完成。
有人能给我指一下可以用来实现这一点的算法或任何API吗?
我已经在谷歌上搜索了几个小时了,到目前为止找不到任何有用的东西:(
只保留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;
您可以毫无问题地创建md5哈希值:
select md5('hello, world');
这将返回一个带有十六进制数字的字符串。
不幸的是,没有将十六进制转换为整数的内置函数,但当您在PL/pgSQL中这样做时,这可能会有所帮助:
https://stackoverflow.com/a/8316731/330315
PostgreSQL为许多列类型提供了哈希函数。如果需要整数哈希值,可以使用hashtext
;如果喜欢bigint
哈希值,则可以使用hashtextextended
。
注意,hashXXXextended
函数需要一个额外的种子参数,0表示不使用种子。
在提交信息中,作者Robert Haas说:
以防万一有人想要一个兼容的64位哈希值使用现有的32位哈希值,使当种子为0时,64位哈希值与32位哈希值匹配。
示例
postgres=# SELECT hashtextextended('test string of type text', 0);
hashtextextended
----------------------
-6578719834206879717
(1 row)
postgres=# SELECT hashtext('test string of type text');
hashtext
-------------
-1790427109
(1 row)
其他数据类型呢
您可以通过检查df hash*
的输出来检查后端上所有可用的哈希函数。下面你可以看到PG 14.0中可用的功能。
hanefi=# df hash*
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+--------------------------+------------------+--------------------------+------
pg_catalog | hash_aclitem | integer | aclitem | func
pg_catalog | hash_aclitem_extended | bigint | aclitem, bigint | func
pg_catalog | hash_array | integer | anyarray | func
pg_catalog | hash_array_extended | bigint | anyarray, bigint | func
pg_catalog | hash_multirange | integer | anymultirange | func
pg_catalog | hash_multirange_extended | bigint | anymultirange, bigint | func
pg_catalog | hash_numeric | integer | numeric | func
pg_catalog | hash_numeric_extended | bigint | numeric, bigint | func
pg_catalog | hash_range | integer | anyrange | func
pg_catalog | hash_range_extended | bigint | anyrange, bigint | func
pg_catalog | hash_record | integer | record | func
pg_catalog | hash_record_extended | bigint | record, bigint | func
pg_catalog | hashbpchar | integer | character | func
pg_catalog | hashbpcharextended | bigint | character, bigint | func
pg_catalog | hashchar | integer | "char" | func
pg_catalog | hashcharextended | bigint | "char", bigint | func
pg_catalog | hashenum | integer | anyenum | func
pg_catalog | hashenumextended | bigint | anyenum, bigint | func
pg_catalog | hashfloat4 | integer | real | func
pg_catalog | hashfloat4extended | bigint | real, bigint | func
pg_catalog | hashfloat8 | integer | double precision | func
pg_catalog | hashfloat8extended | bigint | double precision, bigint | func
pg_catalog | hashhandler | index_am_handler | internal | func
pg_catalog | hashinet | integer | inet | func
pg_catalog | hashinetextended | bigint | inet, bigint | func
pg_catalog | hashint2 | integer | smallint | func
pg_catalog | hashint2extended | bigint | smallint, bigint | func
pg_catalog | hashint4 | integer | integer | func
pg_catalog | hashint4extended | bigint | integer, bigint | func
pg_catalog | hashint8 | integer | bigint | func
pg_catalog | hashint8extended | bigint | bigint, bigint | func
pg_catalog | hashmacaddr | integer | macaddr | func
pg_catalog | hashmacaddr8 | integer | macaddr8 | func
pg_catalog | hashmacaddr8extended | bigint | macaddr8, bigint | func
pg_catalog | hashmacaddrextended | bigint | macaddr, bigint | func
pg_catalog | hashname | integer | name | func
pg_catalog | hashnameextended | bigint | name, bigint | func
pg_catalog | hashoid | integer | oid | func
pg_catalog | hashoidextended | bigint | oid, bigint | func
pg_catalog | hashoidvector | integer | oidvector | func
pg_catalog | hashoidvectorextended | bigint | oidvector, bigint | func
pg_catalog | hashtext | integer | text | func
pg_catalog | hashtextextended | bigint | text, bigint | func
pg_catalog | hashtid | integer | tid | func
pg_catalog | hashtidextended | bigint | tid, bigint | func
pg_catalog | hashvarlena | integer | internal | func
pg_catalog | hashvarlenaextended | bigint | internal, bigint | func
(47 rows)
注意事项
如果你想在不同的系统中有一致的散列,请确保你有相同的排序规则行为。
内置的可整理数据类型为text
、varchar
和char
。如果您有不同的排序规则选项,您可以看到不同的哈希值。例如,与早期版本相比,glibc 2.28(Debian 10,RHEL 8)中翻转的字符串"a-a"one_answers"a+a"的排序顺序。
如果你想在同一台机器上使用散列,你不必担心,只要你不更新glibc
或使用不同的排序规则。
更多详细信息,请访问:https://www.citusdata.com/blog/2020/12/12/dont-let-collation-versions-corrupt-your-postgresql-indexes/
必须是整数吗?pg_crypto模块提供了许多标准散列函数(md5、sha1等)。他们都返回字节。我想你可以去掉一些比特,把字节转换成整数。
bigint太小,无法存储加密哈希。Pg支持的最大非字节二进制类型是uuid。你可以向uuid抛出这样的摘要:
select ('{'||encode( substring(digest('foobar','sha256') from 1 for 16), 'hex')||'}')::uuid;
uuid
--------------------------------------
c3ab8ff1-3720-e8ad-9047-dd39466b3c89
这是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;