Как создать случайную строку, подходящую для идентификатора сеанса в PostgreSQL?

Я хотел бы создать случайную строку для использования в проверке сеанса с помощью PostgreSQL. Я знаю, что могу получить случайное число с SELECT random(), поэтому я попробовал SELECT md5(random()), но это не работает. Как я могу это сделать?

Ответ 1

Я бы предложил это простое решение:

Это довольно простая функция, которая возвращает случайную строку заданной длины:

Create or replace function random_string(length integer) returns text as
$$
declare
  chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
  result text := '';
  i integer := 0;
begin
  if length < 0 then
    raise exception 'Given length cannot be less than 0';
  end if;
  for i in 1..length loop
    result := result || chars[1+random()*(array_length(chars, 1)-1)];
  end loop;
  return result;
end;
$$ language plpgsql;

И использование:

select random_string(15);

Пример вывода:

select random_string(15) from generate_series(1,15);

  random_string
-----------------
 5emZKMYUB9C2vT6
 3i4JfnKraWduR0J
 R5xEfIZEllNynJR
 tMAxfql0iMWMIxM
 aPSYd7pDLcyibl2
 3fPDd54P5llb84Z
 VeywDb53oQfn9GZ
 BJGaXtfaIkN4NV8
 w1mvxzX33NTiBby
 knI1Opt4QDonHCJ
 P9KC5IBcLE0owBQ
 vvEEwc4qfV4VJLg
 ckpwwuG8YbMYQJi
 rFf6TchXTO3XsLs
 axdQvaLBitm6SDP
(15 rows)

Ответ 2

Вы можете исправить свою начальную попытку следующим образом:

SELECT md5(random()::text);

Гораздо проще, чем некоторые другие предложения.: -)

Ответ 3

Основываясь на решении Marcin, вы можете сделать это, используя произвольный алфавит (в данном случае все 62 алфавитно-цифровых символа ASCII):

SELECT array_to_string(array 
       ( 
              select substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', trunc(random() * 62)::integer + 1, 1)
              FROM   generate_series(1, 12)), '');

Ответ 4

Недавно я играл с PostgreSQL, и я думаю, что нашел немного лучшего решения, используя только встроенные методы PostgreSQL - нет pl/pgsql. Единственным ограничением является то, что в настоящее время он генерирует только строки UPCASE или числа или строчные строки.

template1=> SELECT array_to_string(ARRAY(SELECT chr((65 + round(random() * 25)) :: integer) FROM generate_series(1,12)), '');
 array_to_string
-----------------
 TFBEGODDVTDM

template1=> SELECT array_to_string(ARRAY(SELECT chr((48 + round(random() * 9)) :: integer) FROM generate_series(1,12)), '');
 array_to_string
-----------------
 868778103681

Второй аргумент метода generate_series определяет длину строки.

Ответ 5

Вы можете получить 128 бит случайным образом из UUID. Это метод для выполнения работы в современном PostgreSQL.

CREATE EXTENSION pgcrypto;
SELECT gen_random_uuid();

           gen_random_uuid            
--------------------------------------
 202ed325-b8b1-477f-8494-02475973a28f

Может быть, стоит прочитать документы по UUID тоже

Тип данных uuid хранит универсальные уникальные идентификаторы (UUID) в соответствии с RFC 4122, ISO/IEC 9834-8: 2005 и соответствующими стандартами. (Некоторые системы называют этот тип данных глобально уникальным идентификатором или идентификатором GUID.) Этот идентификатор представляет собой 128-битную величину, генерируемую алгоритмом, выбранным для того, чтобы очень маловероятно, что этот же идентификатор будет генерироваться кем-либо еще. в известной вселенной, используя тот же алгоритм. Следовательно, для распределенных систем эти идентификаторы обеспечивают лучшую гарантию уникальности, чем генераторы последовательностей, которые уникальны только в одной базе данных.

Насколько редки столкновения с UUID, или можно предположить? Предполагая, что они случайные,

Приблизительно 100 триллионов UUID версии 4 необходимо будет сгенерировать, чтобы иметь шанс 1 на миллиард одного дубликата ("коллизия"). Вероятность одного столкновения возрастает до 50% только после генерирования 261 UUID (2,3 x 10 ^ 18 или 2,3 квинтиллиона). Соотнесение этих чисел с базами данных и рассмотрение вопроса о том, является ли вероятность коллизии UUID Версии 4 незначительной, рассмотрим файл, содержащий 2,3 квинтиллиона UUID Версии 4, с вероятностью 50%, содержащий одну коллизию UUID. Это будет 36 эксабайт по размеру, без учета других данных или издержек, в тысячи раз больше, чем самые большие базы данных, существующие в настоящее время, которые имеют порядок петабайт. При скорости генерирования 1 миллиарда UUID в секунду потребуется 73 года для генерации UUID для файла. Для его хранения также потребуется около 3,6 млн. 10-терабайтных жестких дисков или кассет с магнитной лентой, что не требует резервного копирования и резервирования. Чтение файла со стандартной скоростью передачи данных с диска в буфер 1 гигабит в секунду потребует более 3000 лет для одного процессора. Так как неисправимая частота ошибок чтения дисков составляет в лучшем случае 1 бит на 1018 бит, в то время как файл будет содержать около 1020 бит, простое чтение файла от начала до конца приведет, по крайней мере, к примерно 100-кратному увеличению количества ошибок. читать UUID, чем дубликаты. Ошибки хранения, сети, питания и других аппаратных и программных средств, несомненно, будут в тысячи раз чаще, чем проблемы с дублированием UUID.

Источник: Википедия

В итоге,

  • UUID стандартизирован.
  • gen_random_uuid() - это 128 бит случайных чисел, хранящихся в 128 битах (2 ** 128 комбинаций). 0-отходов.
  • random() генерирует только 52 бита в PostgreSQL (2 ** 52 комбинации).
  • md5() хранится как UUID 128 бит, но он может быть только случайным, как его вход (52 бит, если использовать random())
  • md5() хранящийся в виде текста, имеет длину 288 бит, но он может быть случайным только в качестве входного значения (52 бита, если используется random()) - более чем в два раза больше UUID и доли случайности)
  • md5() как хеш, может быть настолько оптимизирован, что он мало что делает.
  • UUID очень эффективен для хранения: PostgreSQL предоставляет тип, который точно равен 128 битам. В отличие от text varchar и т.д., varlena хранятся как varlena которого есть накладные расходы на длину строки.
  • Отличный UUID PostgreSQL поставляется с некоторыми операторами, кастингами и функциями по умолчанию.

Ответ 6

Пока он не активен по умолчанию, вы можете активировать одно из основных расширений:

CREATE EXTENSION IF NOT EXISTS pgcrypto;

Затем ваше выражение становится простым вызовом gen_salt(), который генерирует случайную строку:

select gen_salt('md5') from generate_series(1,4);

 gen_salt
-----------
$1$M.QRlF4U
$1$cv7bNJDM
$1$av34779p
$1$ZQkrCXHD

Ведущее число - это хэш-идентификатор. Доступны несколько алгоритмов со своим собственным идентификатором:

  • md5: $1 $
  • bf: $2a $06 $
  • des: no identifier
  • xdes: _J9..

Дополнительная информация о расширениях:


ИЗМЕНИТЬ

Как указывает Эван Кэррол, с версии 9.4 вы можете использовать gen_random_uuid()

http://www.postgresql.org/docs/9.4/static/pgcrypto.html

Ответ 7

Используйте string_agg!

SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '')
FROM   generate_series(1, 45);

Я использую это с MD5 для создания UUID. Я просто хочу случайное значение с большим количеством бит, чем целое число random ().

Ответ 8

Я не думаю, что вы ищете случайную строку как таковую. Что вам нужно для проверки сеанса, это строка, которая гарантированно будет уникальной. Вы храните информацию о проверке сеанса для аудита? В этом случае строка должна быть уникальной между сеансами. Я знаю двух, довольно простых подходов:

  • Используйте последовательность. Хорошо подходит для использования в одной базе данных.
  • Используйте UUID. Универсально уникальная, такая же хорошая и в распределенных средах.

UUID гарантированно уникальны в силу своего алгоритма генерации; эффективно чрезвычайно маловероятно, что вы будете генерировать два одинаковых числа на любой машине в любое время (заметьте, что это намного сильнее, чем на случайных строках, которые имеют гораздо меньшую периодичность, чем UUID).

Вам нужно загрузить расширение uuid-ossp для использования UUID. После установки вызовите любую из доступных функций uuid_generate_vXXX() в ваших вызовах SELECT, INSERT или UPDATE. Тип uuid представляет собой 16-байтовое число, но также имеет строковое представление.

Ответ 9

select * from md5(to_char(random(), '0.9999999999999999'));

Ответ 10

Параметр INTEGER определяет длину строки. Гарантируется, что все 62 символа алфавита будут одинаковыми (в отличие от некоторых других решений, распространяющихся в Интернете).

CREATE OR REPLACE FUNCTION random_string(INTEGER)
RETURNS TEXT AS
$BODY$
SELECT array_to_string(
    ARRAY (
        SELECT substring(
            '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
            FROM (ceil(random()*62))::int FOR 1
        )
        FROM generate_series(1, $1)
    ), 
    ''
)
$BODY$
LANGUAGE sql VOLATILE;

Ответ 11

@Kavius ​​рекомендуется использовать pgcrypto, но вместо gen_salt, а что насчет gen_random_bytes? А как насчет sha512 вместо md5?

create extension if not exists pgcrypto;
select digest(gen_random_bytes(1024), 'sha512');

Docs:

F.25.5. Функции случайных данных

gen_random_bytes (count integer) возвращает bytea

Возвращает количество криптографически сильных случайных байтов. Не более 1024 байты могут быть извлечены за раз. Это делается для того, чтобы избежать слива пул генераторов случайности.

Ответ 12

select encode(decode(md5(random()::text), 'hex')||decode(md5(random()::text), 'hex'), 'base64')

Ответ 13

Вы также можете использовать функцию now():

SELECT md5(now()::text);