md5 () работает с литералом, но не с данными столбца
при проверке в 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
как функция не exist, если он работал в первом запросе? что я делаю неправильно; Как правильно использовать md5()
в SELECT запрос?
4 ответов
функция ожидает в качестве параметра текст. Брось его:
SELECT request_id, md5(request_id::text)
FROM Request
ORDER BY request_id
функция с именем md5, принимающая целочисленный параметр, не существует, но вы можете ее создать:
create function md5(integer)
returns text as $$
select md5(::text);
$$ language sql immutable;
тогда будет 3 подписи для md5:
=> \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 текстового представления целого числа может быть не тем, что вы хотите. Чтобы иметь хэш двоичного файла, подпись md5 принимает bytea
параметр должен быть используется:
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(), 8))::bytea);
$$ language sql immutable;
В общем случае не имеет смысла брать md5 целого числа. Кажется вероятным, что вы пытаетесь скрыть последовательность, чтобы она казалась полуслучайной в порядке. Если это так, есть гораздо лучший способ:
использовать pseudo_encrypt
функция, перечисленная в вики PostgreSQL. Это намного разумнее, чем пытаться взять md5 целого числа, а затем (предположительно) усечь его.
выше не обеспечьте сильную криптографическую случайность, но ни ваш подход. Если вам нужно, чтобы ваши идентификаторы запроса были действительно непредсказуемыми по соображениям безопасности, а не просто неочевидными с первого взгляда, вы должны использовать сильный криптографический генератор случайных чисел и быть готовы справиться с дубликатами с помощью временных окон и т. д.
ошибка немного вводит в заблуждение;md5()
функция существует, просто не для работы над чисел. Используйте встроенный CAST()
функция для преобразования целочисленного поля в текст, и она будет работать:
SELECT request_id, md5(CAST(request_id AS TEXT))
FROM Request
ORDER BY request_id
--1;"c4ca4238a0b923820dcc509a6f75849b"
--2;"c81e728d9d4c2f636f067f89cc14862c"
--etc
Я просто пытаюсь создать неочевидное, неповторяющееся значение, которое может использоваться для поиска записи.
вам нужен биективный хэш. Я использую CRC
функция CPU в пользовательской функции C. Для процессоров, которые не имеют функции, можно использовать таблицу подстановки.
этот подход гарантированно даст вам уникальное "случайное" число для каждого уникального 32-битного ввода.
Если вы знаете, как генерировать функции C (не trivial), будет простой задачей найти, как использовать CRC.