47

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

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

我已经在谷歌上搜索了几个小时,到目前为止找不到任何有用的东西:(

4

5 回答 5

65

只需保留 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;
于 2012-03-21T20:06:25.843 回答
15

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

select md5('hello, world');

这将返回一个带有十六进制数字的字符串。

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

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

于 2012-03-21T17:57:52.397 回答
5

它必须是整数吗?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
于 2012-03-21T18:17:16.860 回答
3

这是 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;
于 2019-10-25T21:13:59.127 回答
3

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)

注意事项

如果您想在不同系统之间保持一致的哈希值,请确保您具有相同的排序规则行为。

内置的可整理数据类型是textvarcharchar。如果您有不同的排序规则选项,您可以看到不同的哈希值。例如,与早期版本相比,glibc 2.28(Debian 10、RHEL 8)中字符串 'a-a' 和 'a+a' 的排序顺序颠倒了。

如果您希望在同一台机器上使用哈希,您不必担心,只要您不更新glibc或使用不同的排序规则。

在以下位置查看更多详细信息:https ://www.citusdata.com/blog/2020/12/12/dont-let-collat​​ion-versions-corrupt-your-postgresql-indexes/

于 2021-10-20T17:58:08.913 回答