我需要将存储在我的数据库中的字符串转换为数值。结果可以是整数(首选)或 Bigint。此转换将在 PL/pgSQL 函数中的数据库端完成。
有人可以指点我一些可用于实现此目的的算法或任何 API 吗?
我已经在谷歌上搜索了几个小时,到目前为止找不到任何有用的东西:(
我需要将存储在我的数据库中的字符串转换为数值。结果可以是整数(首选)或 Bigint。此转换将在 PL/pgSQL 函数中的数据库端完成。
有人可以指点我一些可用于实现此目的的算法或任何 API 吗?
我已经在谷歌上搜索了几个小时,到目前为止找不到任何有用的东西:(
只需保留 MD5 哈希的前 32 位或 64 位。当然,它使 md5 的主要属性无效(=碰撞概率是无穷小),但您仍然会得到广泛的值分散,这可能足以解决您的问题。
从其他答案派生的 SQL 函数:
对于大整数:
create function h_bigint(text) returns bigint as $$
select ('x'||substr(md5($1),1,16))::bit(64)::bigint;
$$ language sql;
对于整数:
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 中这样做,这可能会有所帮助:
它必须是整数吗?pg_crypto模块提供了许多 标准的散列函数(md5、sha1 等)。他们都返回 bytea。我想您可以丢弃一些位并将字节茶转换为整数。
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;
PostgreSQL 有许多列类型的散列函数。hashtext
如果您想要整数哈希值,或者hashtextextended
您更喜欢哈希值,则可以使用bigint
。
请注意,hashXXXextended
函数需要一个额外的种子参数,0 表示不使用种子。
在提交消息中,作者 Robert Haas 说:
万一有人想要一个与现有 32 位哈希值兼容的 64 位哈希值,请在种子为 0 时使 64 位哈希值的低 32 位匹配 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' 和 'a+a' 的排序顺序颠倒了。
如果您希望在同一台机器上使用哈希,您不必担心,只要您不更新glibc
或使用不同的排序规则。
在以下位置查看更多详细信息:https ://www.citusdata.com/blog/2020/12/12/dont-let-collation-versions-corrupt-your-postgresql-indexes/