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



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

872   12  

12 ответов:

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

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

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)

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

SELECT md5(random()::text);

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

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

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

вы можете получить 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 1018 или 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. - Источник wikipedia

в целом,

  • 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, etc которые хранят как a varlena который имеет накладные расходы на длину строки.
  • PostgreSQL nifty UUID поставляется с некоторыми операторами по умолчанию, отливками и функциями.

недавно я играл с 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 метод диктует длину строки.

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

CREATE EXTENSION IF NOT EXISTS pgcrypto;

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

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

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

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

  • md5: $1$
  • bf: $2a$06$
  • des: нет идентификатора
  • xdes: _J9..

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


EDIT

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

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

пожалуйста, используйте string_agg!

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

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

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

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

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

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

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

целочисленный параметр определяет длину строки. Гарантированное покрытие всех 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, )
    ), 
    ''
)
$BODY$
LANGUAGE sql VOLATILE;

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

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

документы:

F. 25. 5. Функции Случайных Данных

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

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

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

Comments

    Ничего не найдено.