Chciałbym utworzyć losowy ciąg znaków do weryfikacji sesji przy użyciu PostgreSQL. Wiem, że mogę uzyskać losową liczbę SELECT random()
, więc próbowałem SELECT md5(random())
, ale to nie działa. W jaki sposób mogę to zrobić?
postgresql
random
gersh
źródło
źródło
random()
nie jest to konieczne). Jeśli nie jest to, co przypuszczam, moja odpowiedź musi być skierowana na bardziej wyrafinowane pytanie.Odpowiedzi:
Proponuję takie proste rozwiązanie:
To dość prosta funkcja, która zwraca losowy ciąg o podanej długości:
I użycie:
Przykładowe dane wyjściowe:
źródło
chars[1+random()*(array_length(chars, 1)-1)]
jechars[ceil(61 * random())]
random()
jest wywoływanylength
razy (jak w wielu innych rozwiązaniach). Czy za każdym razem istnieje bardziej efektywny sposób wyboru spośród 62 znaków? Jak to działa w porównaniu zmd5()
?ORDER BY random()
. Który jest szybszy?Możesz naprawić swoją początkową próbę w następujący sposób:
Znacznie prostsze niż niektóre inne sugestie. :-)
źródło
SELECT concat(md5(random()::text), md5(random()::text));
A jeśli chcesz gdzieś pośrodku (na przykład 50 znaków), możesz wziąć podciąg z tego:SELECT substr(concat(md5(random()::text), md5(random()::text)), 0, 50);
gen_random_uuid()
: szybszej, większej losowości, wydajniejszego przechowywania w bazie danych.SELECT md5(random()::text||random()::text);
lubSELECT md5(random()::text||random()::text||random()::text);
Opierając się na rozwiązaniu Marcina, możesz to zrobić, aby użyć dowolnego alfabetu (w tym przypadku wszystkich 62 znaków alfanumerycznych ASCII):
źródło
Check out this for a totally different method using gen_random_uuid()
: szybciej, więcej losowości, efektywniej przechowywane w bazie danych.Możesz uzyskać 128 bitów losowych z UUID. To jest metoda na wykonanie zadania w nowoczesnym PostgreSQL.
Może być wart czytania docs na zbyt UUID
Jak rzadkie jest zderzenie z UUID lub możliwe do przewidzenia? Zakładając, że są przypadkowe,
źródło: wikipedia
W podsumowaniu,
gen_random_uuid()
to 128 bitów losowych przechowywanych w 128 bitach (2 ** 128 kombinacji). 0-odpadów.random()
generuje tylko 52 bity losowe w PostgreSQL (2 ** 52 kombinacje).md5()
przechowywany jako UUID ma 128 bitów, ale może być tylko tak losowy, jak jego wejście ( 52 bity, jeśli jest używanyrandom()
)md5()
przechowywany jako tekst ma 288 bitów, ale może być tylko tak losowy, jak jego wejście ( 52 bity, jeśli jest używanyrandom()
) - ponad dwukrotnie większy niż UUID i ułamek losowości)md5()
jako skrót może być tak zoptymalizowany, że nie robi wiele efektywnie.text
ivarchar
itp., Które są przechowywane jako wartość,varlena
która ma narzut na długość ciągu.źródło
Ostatnio bawiłem się PostgreSQL i myślę, że znalazłem trochę lepsze rozwiązanie, używając tylko wbudowanych metod PostgreSQL - bez pl / pgsql. Jedynym ograniczeniem jest to, że obecnie generuje tylko łańcuchy UPCASE, liczby lub łańcuchy z małych liter.
Drugi argument
generate_series
metody określa długość ciągu.źródło
array_to_string(ARRAY(SELECT chr((65 + round((random()+my_id-my) * 25)) :: integer) FROM generate_series(1,8)), '')
array_to_string(ARRAY(SELECT chr((65 + round((random() * 25 + id) :: integer % 25 )) :: integer) FROM generate_series(1, 60)), '');
Proszę użyć
string_agg
!Używam tego z MD5 do generowania UUID również. Chcę tylko losowej wartości z większą liczbą bitów niż
random ()
liczba całkowita.źródło
random()
połączyć, dopóki nie uzyskam żądanej liczby bitów. No cóż.Chociaż domyślnie nie jest aktywne, możesz aktywować jedno z podstawowych rozszerzeń:
Wtedy twoja instrukcja staje się prostym wywołaniem gen_salt (), które generuje losowy ciąg:
Wiodąca liczba to identyfikator skrótu. Dostępnych jest kilka algorytmów, każdy z własnym identyfikatorem:
Więcej informacji o rozszerzeniach:
EDYTOWAĆ
Jak wskazał Evan Carrol, od wersji 9.4 można używać
gen_random_uuid()
http://www.postgresql.org/docs/9.4/static/pgcrypto.html
źródło
$1$
? To jest identyfikator typu skrótu (md5 == 1), reszta to wartość losowa.Nie sądzę, że szukasz przypadkowego ciągu jako takiego. To, czego potrzebujesz do weryfikacji sesji, to ciąg, który gwarantuje unikalność. Czy przechowujesz informacje dotyczące weryfikacji sesji na potrzeby audytu? W takim przypadku ciąg musi być unikalny między sesjami. Znam dwa, raczej proste podejścia:
UUID są zagwarantowane być unikalny ze względu na ich algorytm do wytwarzania; skutecznie jest to niezwykle mało prawdopodobne, że wygenerujesz dwie identyczne liczby na dowolnej maszynie, kiedykolwiek, kiedykolwiek (zwróć uwagę, że jest to znacznie silniejsze niż w przypadku ciągów losowych, które mają znacznie mniejszą częstotliwość niż UUID).
Aby używać identyfikatorów UUID, musisz załadować rozszerzenie uuid-ossp. Po zainstalowaniu wywołaj dowolną z dostępnych funkcji uuid_generate_vXXX () w wywołaniach SELECT, INSERT lub UPDATE. Typ uuid to 16-bajtowa liczba, ale ma również reprezentację w postaci ciągu.
źródło
Parametr INTEGER określa długość łańcucha. Gwarantowane pokrycie wszystkich 62 znaków alfanumerycznych z jednakowym prawdopodobieństwem (w przeciwieństwie do niektórych innych rozwiązań krążących po Internecie).
źródło
Check out this for a totally different method using gen_random_uuid()
: szybciej, więcej losowości, efektywniej przechowywane w bazie danych.gen_random_uuid()
pojawił się w wersji 9.4, o ile wiem, która została wydana 2014-12-18, ponad rok po udzielonej przez Ciebie odpowiedzi. Dodatkowy czubek: odpowiedź ma dopiero 3 i pół roku :-) Ale masz rację, skoro już mamygen_random_uuid()
, to powinno być używane. Dlatego głosuję za twoją odpowiedzią.@Kavius zaleca używanie
pgcrypto
, ale zamiast tegogen_salt
, co z tymgen_random_bytes
? A możesha512
zamiast tegomd5
?Dokumenty:
źródło
select * from md5(to_char(random(), '0.9999999999999999'));
źródło
źródło