PostgreSQL을 사용하여 세션 확인에 사용할 임의의 문자열을 만들고 싶습니다. 를 사용하여 난수를 얻을 수 있다는 것을 알고 SELECT random()
있으므로을 시도 SELECT md5(random())
했지만 작동하지 않습니다. 어떻게 할 수 있습니까?
random()
ness가 필요하지 않은 경우). 내가 가정하는 것이 아니라면, 내 대답은 정제 된 질문에 맞춰져야합니다.
PostgreSQL을 사용하여 세션 확인에 사용할 임의의 문자열을 만들고 싶습니다. 를 사용하여 난수를 얻을 수 있다는 것을 알고 SELECT random()
있으므로을 시도 SELECT md5(random())
했지만 작동하지 않습니다. 어떻게 할 수 있습니까?
random()
ness가 필요하지 않은 경우). 내가 가정하는 것이 아니라면, 내 대답은 정제 된 질문에 맞춰져야합니다.
답변:
이 간단한 해결책을 제안합니다.
이것은 주어진 길이의 임의의 문자열을 반환하는 아주 간단한 함수입니다.
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)
chars[1+random()*(array_length(chars, 1)-1)]
와 함께chars[ceil(61 * random())]
ORDER BY random()
. 어느 것이 더 빠릅니까?
다음과 같이 초기 시도를 수정할 수 있습니다.
SELECT md5(random()::text);
다른 제안보다 훨씬 간단합니다. :-)
SELECT concat(md5(random()::text), md5(random()::text));
중간 어딘가 (예 : 50 자)를 원하면 다음 과 같은 하위 문자열을 사용할 수 있습니다. SELECT substr(concat(md5(random()::text), md5(random()::text)), 0, 50);
gen_random_uuid()
.
Marcin의 솔루션을 기반으로이 작업을 수행하여 임의의 알파벳을 사용할 수 있습니다 (이 경우 62 개의 ASCII 영숫자 문자).
SELECT array_to_string(array
(
select substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', trunc(random() * 62)::integer + 1, 1)
FROM generate_series(1, 12)), '');
Check out this for a totally different method using gen_random_uuid()
: 더 빠르고, 더 무작위 적이며, 더 효율적으로 데이터베이스에 저장됩니다.
UUID에서 128 비트를 무작위로 얻을 수 있습니다. 이것은 최신 PostgreSQL에서 작업을 수행하는 방법입니다.
CREATE EXTENSION pgcrypto;
SELECT gen_random_uuid();
gen_random_uuid
--------------------------------------
202ed325-b8b1-477f-8494-02475973a28f
수 있음 도 UUID에 문서를 읽을 가치
데이터 유형 uuid는 RFC 4122, ISO / IEC 9834-8 : 2005 및 관련 표준에 정의 된 대로 UUID (Universally Unique Identifier)를 저장 합니다. (일부 시스템에서는이 데이터 유형을 전역 고유 식별자 또는 GUID라고합니다.)이 식별자는 다른 사람이 동일한 식별자를 생성 할 가능성이 거의 없도록 선택한 알고리즘에 의해 생성되는 128 비트 수량 입니다. 동일한 알고리즘을 사용하여 알려진 우주에서. 따라서 분산 시스템의 경우 이러한 식별자는 단일 데이터베이스 내에서만 고유 한 시퀀스 생성기보다 더 나은 고유성을 보장합니다.
UUID와의 충돌은 얼마나 드물거나 추측 할 수 있습니까? 무작위라고 가정하면
단일 복제 ( "충돌")의 10 억분의 1의 기회를 가지려면 약 100 조 개의 버전 4 UUID를 생성해야합니다. 한 번의 충돌 가능성은 261 개의 UUID (2.3 x 10 ^ 18 또는 2.3 quintillion)가 생성 된 후에 만 50 %로 증가합니다. 이 숫자를 데이터베이스와 연결하고 버전 4 UUID 충돌 가능성이 무시할 수 있는지 여부를 고려할 때, UUID 충돌을 포함 할 확률이 50 % 인 2.3 quintillion 버전 4 UUID가 포함 된 파일을 고려하십시오. 다른 데이터 나 오버 헤드가 없다고 가정하면 크기가 36 엑사 바이트가되며, 현재 존재하는 가장 큰 데이터베이스 (약 페타 바이트)보다 수천 배 더 큽니다. 초당 10 억 UUID가 생성되는 속도로 파일에 대한 UUID를 생성하는 데 73 년이 걸립니다. 또한 약 3 개가 필요합니다. 6 백만 개의 10 테라 바이트 하드 드라이브 또는 테이프 카트리지로 백업이나 중복성이 없다고 가정합니다. 초당 1 기가비트의 일반적인 "디스크 대 버퍼"전송 속도로 파일을 읽으려면 단일 프로세서에 3000 년 이상이 필요합니다. 드라이브의 복구 할 수없는 읽기 오류율은 읽기 1018 비트 당 1 비트이고 파일에는 약 1020 비트가 포함되어 있기 때문에 파일을 끝에서 끝까지 한 번 읽는 것만으로도 적어도 약 100 배 더 많은 오류가 발생합니다. 중복보다 UUID를 읽습니다. 스토리지, 네트워크, 전원 및 기타 하드웨어 및 소프트웨어 오류는 의심 할 여지없이 UUID 복제 문제보다 수천 배 더 자주 발생합니다. 초당 1 기가비트의 전송 속도는 단일 프로세서에 3000 년 이상이 필요합니다. 드라이브의 복구 할 수없는 읽기 오류율은 읽기 1018 비트 당 1 비트이고 파일에는 약 1020 비트가 포함되어 있기 때문에 파일을 끝에서 끝까지 한 번 읽는 것만으로도 적어도 약 100 배 더 많은 오류가 발생합니다. 중복보다 UUID를 읽습니다. 스토리지, 네트워크, 전원 및 기타 하드웨어 및 소프트웨어 오류는 의심 할 여지없이 UUID 복제 문제보다 수천 배 더 자주 발생합니다. 초당 1 기가비트의 전송 속도는 단일 프로세서에 3000 년 이상이 필요합니다. 드라이브의 복구 할 수없는 읽기 오류율은 읽기 1018 비트 당 1 비트이고 파일에는 약 1020 비트가 포함되어 있기 때문에 파일을 끝에서 끝까지 한 번 읽는 것만으로도 적어도 약 100 배 더 많은 오류가 발생합니다. 중복보다 UUID를 읽습니다. 스토리지, 네트워크, 전원 및 기타 하드웨어 및 소프트웨어 오류는 의심 할 여지없이 UUID 복제 문제보다 수천 배 더 자주 발생합니다.
출처 : wikipedia
요약해서 말하자면,
gen_random_uuid()
128 비트 (2 ** 128 개 조합)에 저장된 128 비트 랜덤입니다. 0- 폐기물.random()
PostgreSQL에서는 52 비트 만 무작위로 생성됩니다 (2 ** 52 조합).md5()
UUID로 저장되는 것은 128 비트이지만 입력만큼만 임의적 일 수 있습니다 ( 사용하는 경우 52 비트random()
).md5()
텍스트로 저장되는 것은 288 비트이지만 입력만큼만 임의적 일 수 있습니다 ( 사용하는 경우 52 비트random()
)-UUID 크기의 두 배와 임의성의 일부 이상)md5()
해시로 최적화되어 효과적으로 많은 작업을 수행하지 않습니다.text
와 varchar
등, A와 저장되는 varlena
문자열의 길이의 오버 헤드 갖는다.나는 최근에 PostgreSQL을 가지고 놀았고 pl / pgsql이 아닌 내장 PostgreSQL 메서드 만 사용하여 조금 더 나은 솔루션을 찾은 것 같습니다. 유일한 제한은 현재 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
메서드 의 두 번째 인수 는 문자열의 길이를 지정합니다.
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)), '');
이용하십시오 string_agg
!
SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '')
FROM generate_series(1, 45);
MD5와 함께 이것을 사용하여 UUID도 생성하고 있습니다. random ()
정수 보다 비트가 더 많은 임의의 값을 원합니다 .
random()
원하는 비트 수를 얻을 때까지 연결 하면됩니다. 오 잘.
기본적으로 활성화되지 않은 상태에서 핵심 확장 중 하나를 활성화 할 수 있습니다.
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
선행 번호는 해시 식별자입니다. 각각 고유 한 식별자가있는 여러 알고리즘을 사용할 수 있습니다.
확장에 대한 추가 정보 :
편집하다
Evan Carrol이 지적했듯이 v9.4부터 다음을 사용할 수 있습니다. gen_random_uuid()
$1$
? 이것은 해시 유형 식별자 (md5 == 1)이고 나머지는 무작위 값입니다.
나는 당신이 그 자체로 임의의 문자열을 찾고 있다고 생각하지 않습니다. 세션 확인에 필요한 것은 고유함이 보장되는 문자열입니다. 감사를 위해 세션 확인 정보를 저장합니까? 이 경우 세션간에 고유 한 문자열이 필요합니다. 나는 두 가지 간단한 접근 방식을 알고 있습니다.
UUID는 생성 알고리즘 덕분에 고유 한 것으로 보장 됩니다. 사실상 어떤 컴퓨터에서든 항상 두 개의 동일한 숫자를 생성 할 가능성 은 극히 낮습니다 (UUID보다 주기성이 훨씬 작은 임의 문자열보다 훨씬 강력합니다).
UUID를 사용하려면 uuid-ossp 확장을로드해야합니다. 설치가 끝나면 SELECT, INSERT 또는 UPDATE 호출에서 사용 가능한 uuid_generate_vXXX () 함수를 호출하십시오. uuid 유형은 16 바이트 숫자이지만 문자열 표현도 있습니다.
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;
Check out this for a totally different method using gen_random_uuid()
: 더 빠르고, 더 무작위 적이며, 더 효율적으로 데이터베이스에 저장됩니다.
gen_random_uuid()
말하면, 제가 아는 한 버전 9.4에 나타났습니다 . 2014 년 12 월 18 일에 릴리스 된 것은 귀하가 반대표를 던진 지 1 년이 지난 후입니다. 추가 nitpick : 대답은 겨우 3 년 반입니다. :-)하지만 당신이 맞아요, 이제 우리는 gen_random_uuid()
, 이것이 사용해야하는 것입니다. 따라서 나는 당신의 대답을 찬성 할 것입니다.
@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 * from md5(to_char(random(), '0.9999999999999999'));
select encode(decode(md5(random()::text), 'hex')||decode(md5(random()::text), 'hex'), 'base64')