7

在测试PostgreSQL 的md5()功能时,我注意到非常奇怪的行为:

按预期工作

SELECT md5('abc')
--"900150983cd24fb0d6963f7d28e17f72"

但是在查询中使用 md5() 函数:

SELECT request_id, md5(request_id)
FROM Request
ORDER BY request_id

导致此错误:

ERROR:  function md5(integer) does not exist
LINE 1: SELECT request_id, md5(request_id)
                           ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

********** Error **********

ERROR: function md5(integer) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 20

如果该函数在第一个查询中起作用,它怎么可能不存在?我究竟做错了什么; md5()在 SELECT 查询中使用的正确方法是什么?

4

4 回答 4

14

该函数需要文本作为参数。投射它:

SELECT request_id, md5(request_id::text)
FROM Request
ORDER BY request_id

不存在名为 md5 的接受整数参数的函数,但您可以创建它:

create function md5(integer)
returns text as $$

select md5($1::text);

$$ language sql immutable;

那么md5会有3个签名:

=> \df md5
                          List of functions
   Schema   | Name | Result data type | Argument data types |  Type  
------------+------+------------------+---------------------+--------
 pg_catalog | md5  | text             | bytea               | normal
 pg_catalog | md5  | text             | text                | normal
 public     | md5  | text             | integer             | normal

正如对此答案的评论中所指出的,整数文本表示的 md5 哈希可能不是您想要的。要获得二进制的哈希,bytea应使用接受参数的 md5 签名:

select md5(('\x' || right('0000000' || to_hex(200), 8))::bytea);
               md5                
----------------------------------
 b7b436d004c1cc0501bee9e296d2eaa4

并替换之前创建的函数:

create or replace function md5(integer)
returns text as $$

select md5(('\x' || right('0000000' || to_hex($1), 8))::bytea);

$$ language sql immutable;
于 2013-03-24T17:21:01.407 回答
3

一般来说,取整数的 md5 没有多大意义。您似乎试图掩盖一个序列,使其按顺序显示为半随机。如果是这样,有一个更好的方法:

使用pseudo_encryptPostgreSQL wiki 上列出的函数。这比尝试取整数的 md5 然后(大概)截断它要明智得多。

上面没有提供强大的加密随机性,但您的方法也没有。如果您出于安全原因需要您的请求 ID 真正不可预测,而不仅仅是一目了然,您应该使用强大的加密随机数生成器,并准备好使用时间窗口等处理重复。

于 2013-03-24T22:37:28.233 回答
1

这个错误有点误导;该md5()函数存在,只是不适用于整数。使用嵌入式CAST()函数将整数字段转换为文本,它将起作用:

SELECT request_id, md5(CAST(request_id AS TEXT))
FROM Request
ORDER BY request_id

--1;"c4ca4238a0b923820dcc509a6f75849b"
--2;"c81e728d9d4c2f636f067f89cc14862c"
--etc
于 2013-03-24T17:22:16.910 回答
0

我只是想生成一个不明显、不重复的值,可用于查找记录。

你需要的是一个双射哈希。我CRC在自定义 C 函数中使用 CPU 函数。对于没有该功能的 CPU,可以使用查找表。

这种方法保证为每个唯一的 32 位输入提供一个唯一的“随机查找”数字。

如果您知道如何生成 C 函数(不是微不足道的),那么查找如何使用 CRC 将是一项简单的任务。

于 2017-06-08T17:41:15.487 回答