Как создать случайную строку, которая подходит для идентификатора сеанса в PostgreSQL?
Я хотел бы сделать случайную строку для использования в проверке сеанса с помощью PostgreSQL. Я знаю, что могу получить случайное число с SELECT random(), Так что я пробовал SELECT md5(random()), но это не работает. Как я могу это сделать?
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 которые хранят как avarlenaкоторый имеет накладные расходы на длину строки.- 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..
дополнительная информация о расширениях:
- pgCrypto: http://www.postgresql.org/docs/9.2/static/pgcrypto.html
- включенные расширения:http://www.postgresql.org/docs/9.2/static/contrib.html
EDIT
как указано Эваном Кэрролом, с v9. 4 Вы можете использовать
gen_random_uuid()
пожалуйста, используйте
string_agg!SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '') FROM generate_series(1, 45);Я использую это с MD5 для создания UUID также. Я просто хочу случайное значение с большим количеством битов, чем
random ()целое число.
Я не думаю, что вы ищете случайную строку как таковую. То, что вам нужно для проверки сеанса, - это строка, которая гарантированно будет уникальной. Вы храните информацию о проверке сеанса для аудита? В этом случае вам нужно, чтобы строка была уникальной между сеансами. Я знаю два, довольно простых подхода:
- использовать последовательность. Хорошо подходит для использования в одной базе данных.
- используйте UUID. Универсально уникальный, так хорошо на распределенных средах тоже.
UUIDs - это гарантированный быть уникальным в силу их алгоритма для генерации; эффективно это очень маловероятно, что вы будете генерировать два одинаковых числа на любой машине, в любое время, когда-либо (обратите внимание, что это намного сильнее, чем на случайных строках, которые имеют гораздо меньшую периодичность, чем UUIDs).
вам нужно загрузить идентификатор UUID-ОССП расширения, чтобы использовать идентификаторы UUID. После установки, позвоните любой из доступных функции uuid_generate_vXXX () в вызовах SELECT, INSERT или UPDATE. Тип uuid является 16-байтовым числом, но он также имеет строковое представление.
целочисленный параметр определяет длину строки. Гарантированное покрытие всех 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 байты могут быть извлечены одновременно. Это позволит избежать слива генератор случайностей бассейн.
Comments