Ik wil graag een willekeurige reeks maken voor gebruik bij sessieverificatie met PostgreSQL. Ik weet dat ik een willekeurig getal kan krijgen met SELECT random()
, dus ik heb SELECT md5(random())
geprobeerd, maar dat werkt niet. Hoe kan ik dit doen?
Antwoord 1, autoriteit 100%
U kunt uw eerste poging als volgt oplossen:
SELECT md5(random()::text);
Veel eenvoudiger dan sommige van de andere suggesties. 🙂
Antwoord 2, autoriteit 40%
Ik stel deze eenvoudige oplossing voor:
Dit is een vrij eenvoudige functie die een willekeurige string van de opgegeven lengte retourneert:
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;
En het gebruik:
select random_string(15);
Voorbeelduitvoer:
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)
Antwoord 3, autoriteit 12%
Voortbouwend op de oplossing van Marcin, kunt u dit doen door een willekeurig alfabet te gebruiken (in dit geval alle 62 ASCII-alfanumerieke tekens):
SELECT array_to_string(array
(
select substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', trunc(random() * 62)::integer + 1, 1)
FROM generate_series(1, 12)), '');
Antwoord 4, autoriteit 12%
Je kunt 128 bits willekeurig krijgen van een UUID. Dit is de methode om de klus te klaren in moderne PostgreSQL.
CREATE EXTENSION pgcrypto;
SELECT gen_random_uuid();
gen_random_uuid
--------------------------------------
202ed325-b8b1-477f-8494-02475973a28f
Misschien de documenten op UUID ook lezen
Het gegevenstype uuid slaat Universally Unique Identifiers (UUID) op zoals gedefinieerd door RFC 4122, ISO/IEC 9834-8:2005en gerelateerde standaarden. (Sommige systemen verwijzen in plaats daarvan naar dit gegevenstype als een globally unique identifier of GUID.) Deze identifier is een 128-bits hoeveelheiddie wordt gegenereerd door een algoritme dat is gekozen om het zeer onwaarschijnlijk te maken dat hetzelfde identifier wordt gegenereerd door iemand anders in het bekende universum met behulp van hetzelfde algoritme. Daarom bieden deze identifiers voor gedistribueerde systemen een betere uniciteitsgarantie dan sequentiegeneratoren, die alleen uniek zijn binnen een enkele database.
Hoe zeldzaam is een botsing met UUID, of te raden? Ervan uitgaande dat ze willekeurig zijn,
Er zouden ongeveer 100 biljoen versie 4 UUID’s moeten worden gegenereerd om een kans van 1 op een miljard te hebben op een enkel duplicaat (“botsing”). De kans op één botsing stijgt pas tot 50% nadat er 261 UUID’s (2,3 x 10^18 of 2,3 quintillion) zijn gegenereerd. Als u deze getallen relateert aan databases, en rekening houdt met de vraag of de kans op een UUID-botsing van versie 4 verwaarloosbaar is, overweeg dan een bestand met 2,3 triljoen versie 4 UUID’s, met een kans van 50% op één UUID-botsing. Het zou 36 exabytes groot zijn, uitgaande van geen andere gegevens of overhead, duizenden keren groter dan de grootste databases die momenteel bestaan, die in de orde van petabytes zijn. Met een snelheid van 1 miljard UUID’s die per seconde worden gegenereerd, zou het 73 jaar duren om de UUID’s voor het bestand te genereren. Er zouden ook ongeveer 3,6 miljoen 10 terabyte harde schijven of tapecartridges nodig zijn om het op te slaan, ervan uitgaande dat er geen back-ups of redundantie zijn. Het lezen van het bestand met een typische “schijf-naar-buffer” overdrachtssnelheid van 1 gigabit per seconde zou meer dan 3000 jaar vergen voor een enkele processor. Aangezien het onherstelbare leesfoutpercentage van schijven op zijn best 1 bit per 1018 bits is, terwijl het bestand ongeveer 1020 bits zou bevatten, zou het slechts één keer lezen van het bestand van begin tot eind resulteren in op zijn minst ongeveer 100 keer meer fouten. lees UUID’s dan duplicaten. Opslag-, netwerk-, stroom- en andere hardware- en softwarefouten zouden ongetwijfeld duizenden keren vaker voorkomen dan UUID-duplicatieproblemen.
bron: wikipedia
Samengevat,
- UUID is gestandaardiseerd.
gen_random_uuid()
is 128 bits willekeurig opgeslagen in 128 bits (2**128 combinaties). 0-afval.random()
genereert slechts 52 bits willekeurig in PostgreSQL (2**52 combinaties) .md5()
opgeslagen als UUID is 128 bits, maar het kan alleen zo willekeurig zijn als de invoer (52 bits bij gebruik vanrandom()
)md5()
opgeslagen als tekst is 288 bits, maar het kan alleen zo willekeurig zijn als de invoer (52 bits bij gebruik vanrandom()
) – meer dan tweemaal de grootte van een UUID en een fractie van de willekeur)md5()
als hash kan zo worden geoptimaliseerd dat het niet veel doet.- UUID is zeer efficiënt voor opslag: PostgreSQL biedt een type dat precies 128 bits is. In tegenstelling tot
text
envarchar
, enz. die worden opgeslagen als eenvarlena
die overhead heeft voor de lengte van de string. - De handige UUID van PostgreSQL wordt geleverd met enkele standaardoperators, castings en functies.
Antwoord 5, autoriteit 6%
Ik speelde onlangs met PostgreSQL en ik denk dat ik een iets betere oplossing heb gevonden, door alleen ingebouwde PostgreSQL-methoden te gebruiken – geen pl/pgsql. De enige beperking is dat het momenteel alleen UPCASE-tekenreeksen genereert, of cijfers of tekenreeksen in kleine letters.
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
Het tweede argument voor de methode generate_series
bepaalt de lengte van de string.
Antwoord 6, autoriteit 6%
Gebruik a.u.b. string_agg
!
SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '')
FROM generate_series(1, 45);
Ik gebruik dit met MD5 om ook een UUID te genereren. Ik wil gewoon een willekeurige waarde met meer bits dan een random ()
geheel getal.
Antwoord 7, autoriteit 4%
Hoewel standaard niet actief, kunt u een van de kernextensies activeren:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
Dan wordt je statement een simpele aanroep naar gen_salt() die een willekeurige string genereert:
select gen_salt('md5') from generate_series(1,4);
gen_salt
-----------
$1$M.QRlF4U
$1$cv7bNJDM
$1$av34779p
$1$ZQkrCXHD
Het eerste nummer is een hash-ID. Er zijn verschillende algoritmen beschikbaar, elk met hun eigen identifier:
- md5: $1$
- bf: $2a$06$
- des: geen identificatie
- xdes: _J9..
Meer informatie over extensies:
- pgCrypto: http://www.postgresql.org/docs/9.2 /static/pgcrypto.html
- Inbegrepen extensies: http://www.postgresql.org/docs/ 9.2/static/contrib.html
BEWERKEN
Zoals aangegeven door Evan Carrol, kunt u vanaf v9.4 gen_random_uuid()
gebruiken
http://www.postgresql.org/docs/9.4/static /pgcrypto.html
Antwoord 8, autoriteit 3%
@Kavius raadt aan om pgcrypto
te gebruiken , maar hoe zit het met gen_random_bytes
in plaats van gen_random_bytes
? En hoe zit het met sha512
in plaats van md5
?
create extension if not exists pgcrypto;
select digest(gen_random_bytes(1024), 'sha512');
Documenten:
F.25.5. Willekeurige gegevensfuncties
gen_random_bytes(count integer) geeft bytea terug
Retouren tellen cryptografisch sterke willekeurige bytes. Maximaal 1024
bytes kunnen tegelijk worden geëxtraheerd. Dit is om te voorkomen dat de
willekeurig generator pool.
Antwoord 9, autoriteit 2%
De parameter INTEGER definieert de lengte van de string. Dekt gegarandeerd alle 62 alfanumtekens met gelijke waarschijnlijkheid (in tegenstelling tot sommige andere oplossingen die rondzweven op internet).
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;
Antwoord 10, autoriteit 2%
Ik denk niet dat je per se op zoek bent naar een willekeurige string. Wat u nodig heeft voor sessieverificatie, is een tekenreeks die gegarandeerd uniek is. Bewaart u informatie over sessieverificatie voor controle? In dat geval moet de string uniek zijn tussen sessies. Ik ken twee, vrij eenvoudige benaderingen:
- Gebruik een reeks. Goed voor gebruik op een enkele database.
- Gebruik een UUID. Universeel uniek, dus ook goed in gedistribueerde omgevingen.
UUID’s zijn gegarandeerduniek te zijn vanwege hun algoritme voor het genereren; in feite is het uiterstonwaarschijnlijk dat u twee identieke getallen op welke machine dan ook, op elk moment, ooit zult genereren (merk op dat dit veel sterker is dan op willekeurige reeksen, die een veel kleinere periodiciteit dan UUID’s).
U moet de uuid-ossp-extensie laden om UUID’s te gebruiken. Na de installatie roept u een van de beschikbare uuid_generate_vXXX()-functies aan in uw SELECT-, INSERT- of UPDATE-aanroepen. Het uuid-type is een getal van 16 bytes, maar het heeft ook een tekenreeksrepresentatie.
Antwoord 11, autoriteit 2%
select * from md5(to_char(random(), '0.9999999999999999'));