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

Sal*_*gzi 31 postgresql plpgsql postgresql-8.4

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

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

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

Dan*_*ité 42

只需保留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;
Run Code Online (Sandbox Code Playgroud)

对于int:

create function h_int(text) returns int as $$
 select ('x'||substr(md5($1),1,8))::bit(32)::int;
$$ language sql;
Run Code Online (Sandbox Code Playgroud)

  • `('x'||` 条件语句有什么作用? (3认同)
  • @MichaelYoo:`||`运算符用于字符串连接(只有MySQL和受C启发的编程语言将`||`解释为逻辑OR,它不是SQL中的标准解释)。 (2认同)
  • 我知道了.我认为只是将十六进制表示"unhex"为二进制,然后转换为位,是吗?(因为Postgres没有unhex?)我看到的例子总是将'x'放在引号之外,比如x'1b1c2f',在这种情况下,如何在字符串文字"x"前面加上?即CONCAT()也会工作吗? (2认同)

Abd*_*ldı 24

PostgreSQL 具有适用于许多列类型的哈希函数。hashtext如果您需要整数哈希值,或者hashtextextended您更喜欢bigint哈希值,则可以使用。

\n

请注意,hashXXXextended函数需要一个额外的种子参数,0 表示不会使用种子。

\n

作者 Robert Haas 在提交消息中说道:

\n
\n

以防万一有人想要一个与现有 32 位哈希值兼容的 64 位哈希值,请在种子为 0 时使 64 位哈希值的低 32 位与 32 位哈希值相匹配。

\n
\n

例子

\n
postgres=# SELECT hashtextextended(\'test string of type text\', 0);\n   hashtextextended\n----------------------\n -6578719834206879717\n(1 row)\n\npostgres=# SELECT hashtext(\'test string of type text\');\n  hashtext\n-------------\n -1790427109\n(1 row)\n
Run Code Online (Sandbox Code Playgroud)\n

那么其他数据类型呢?

\n

您可以通过检查 的输出来检查后端上所有可用的哈希函数\\df hash*。下面您可以看到 PG 14.0 中可用的功能。

\n
hanefi=# \\df hash*\n                                     List of functions\n   Schema   |           Name           | Result data type |   Argument data types    | Type\n------------+--------------------------+------------------+--------------------------+------\n pg_catalog | hash_aclitem             | integer          | aclitem                  | func\n pg_catalog | hash_aclitem_extended    | bigint           | aclitem, bigint          | func\n pg_catalog | hash_array               | integer          | anyarray                 | func\n pg_catalog | hash_array_extended      | bigint           | anyarray, bigint         | func\n pg_catalog | hash_multirange          | integer          | anymultirange            | func\n pg_catalog | hash_multirange_extended | bigint           | anymultirange, bigint    | func\n pg_catalog | hash_numeric             | integer          | numeric                  | func\n pg_catalog | hash_numeric_extended    | bigint           | numeric, bigint          | func\n pg_catalog | hash_range               | integer          | anyrange                 | func\n pg_catalog | hash_range_extended      | bigint           | anyrange, bigint         | func\n pg_catalog | hash_record              | integer          | record                   | func\n pg_catalog | hash_record_extended     | bigint           | record, bigint           | func\n pg_catalog | hashbpchar               | integer          | character                | func\n pg_catalog | hashbpcharextended       | bigint           | character, bigint        | func\n pg_catalog | hashchar                 | integer          | "char"                   | func\n pg_catalog | hashcharextended         | bigint           | "char", bigint           | func\n pg_catalog | hashenum                 | integer          | anyenum                  | func\n pg_catalog | hashenumextended         | bigint           | anyenum, bigint          | func\n pg_catalog | hashfloat4               | integer          | real                     | func\n pg_catalog | hashfloat4extended       | bigint           | real, bigint             | func\n pg_catalog | hashfloat8               | integer          | double precision         | func\n pg_catalog | hashfloat8extended       | bigint           | double precision, bigint | func\n pg_catalog | hashhandler              | index_am_handler | internal                 | func\n pg_catalog | hashinet                 | integer          | inet                     | func\n pg_catalog | hashinetextended         | bigint           | inet, bigint             | func\n pg_catalog | hashint2                 | integer          | smallint                 | func\n pg_catalog | hashint2extended         | bigint           | smallint, bigint         | func\n pg_catalog | hashint4                 | integer          | integer                  | func\n pg_catalog | hashint4extended         | bigint           | integer, bigint          | func\n pg_catalog | hashint8                 | integer          | bigint                   | func\n pg_catalog | hashint8extended         | bigint           | bigint, bigint           | func\n pg_catalog | hashmacaddr              | integer          | macaddr                  | func\n pg_catalog | hashmacaddr8             | integer          | macaddr8                 | func\n pg_catalog | hashmacaddr8extended     | bigint           | macaddr8, bigint         | func\n pg_catalog | hashmacaddrextended      | bigint           | macaddr, bigint          | func\n pg_catalog | hashname                 | integer          | name                     | func\n pg_catalog | hashnameextended         | bigint           | name, bigint             | func\n pg_catalog | hashoid                  | integer          | oid                      | func\n pg_catalog | hashoidextended          | bigint           | oid, bigint              | func\n pg_catalog | hashoidvector            | integer          | oidvector                | func\n pg_catalog | hashoidvectorextended    | bigint           | oidvector, bigint        | func\n pg_catalog | hashtext                 | integer          | text                     | func\n pg_catalog | hashtextextended         | bigint           | text, bigint             | func\n pg_catalog | hashtid                  | integer          | tid                      | func\n pg_catalog | hashtidextended          | bigint           | tid, bigint              | func\n pg_catalog | hashvarlena              | integer          | internal                 | func\n pg_catalog | hashvarlenaextended      | bigint           | internal, bigint         | func\n(47 rows)\n
Run Code Online (Sandbox Code Playgroud)\n

注意事项

\n

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

\n

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

\n

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

\n

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

\n

  • 根据此讨论 https://www.postgresql.org/message-id/CABUevExTx2whgSpKaoMVowDxBe%3Dpm7w4LJkb%3D-k8NTohQT12Kg%40mail.gmail.com hash**** 系列函数供内部使用,可能会在未来版本中发生变化相同输入的不同哈希值。在生产系统中依赖它们是有风险的。 (3认同)

a_h*_*ame 14

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

select md5('hello, world');
Run Code Online (Sandbox Code Playgroud)

这将返回一个十六进制数字的字符串.

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

/sf/answers/582171201/


dbe*_*hur 5

它必须是整数吗?所述pg_crypto 模块提供了许多标准的散列函数(MD5,SHA1,等等)。他们都返回 bytea。我想你可以扔掉一些位并将 bytea 转换为整数。

bigint 太小,无法存储加密哈希。Pg 支持的最大的非字节二进制类型是 uuid。您可以像这样将摘要转换为 uuid:

select ('{'||encode( substring(digest('foobar','sha256') from 1 for 16), 'hex')||'}')::uuid;
                 uuid                 
--------------------------------------
 c3ab8ff1-3720-e8ad-9047-dd39466b3c89
Run Code Online (Sandbox Code Playgroud)