[postgresql] PostgreSQL에서 세션 ID에 적합한 임의의 문자열을 어떻게 생성합니까?

PostgreSQL을 사용하여 세션 확인에 사용할 임의의 문자열을 만들고 싶습니다. 를 사용하여 난수를 얻을 수 있다는 것을 알고 SELECT random()있으므로을 시도 SELECT md5(random())했지만 작동하지 않습니다. 어떻게 할 수 있습니까?



답변

이 간단한 해결책을 제안합니다.

이것은 주어진 길이의 임의의 문자열을 반환하는 아주 간단한 함수입니다.

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);

다른 제안보다 훨씬 간단합니다. 🙂


답변

Marcin의 솔루션을 기반으로이 작업을 수행하여 임의의 알파벳을 사용할 수 있습니다 (이 경우 62 개의 ASCII 영숫자 문자).

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


답변

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

요약해서 말하자면,

  • UUID가 표준화되었습니다.
  • gen_random_uuid()128 비트 (2 ** 128 개 조합)에 저장된 128 비트 랜덤입니다. 0- 폐기물.
  • random() PostgreSQL에서는 52 비트 만 무작위로 생성됩니다 (2 ** 52 조합).
  • md5()UUID로 저장되는 것은 128 비트이지만 입력만큼만 임의적 일 수 있습니다 ( 사용하는 경우 52 비트random() ).
  • md5()텍스트로 저장되는 것은 288 비트이지만 입력만큼만 임의적 일 수 있습니다 ( 사용하는 경우 52 비트random() )-UUID 크기의 두 배와 임의성의 일부 이상)
  • md5() 해시로 최적화되어 효과적으로 많은 작업을 수행하지 않습니다.
  • UUID는 저장소에 매우 효율적입니다. PostgreSQL은 정확히 128 비트 유형을 제공합니다. 달리 textvarchar등, A와 저장되는 varlena문자열의 길이의 오버 헤드 갖는다.
  • PostgreSQL 멋진 UUID에는 기본 연산자, 캐스팅 및 기능이 함께 제공됩니다.

답변

나는 최근에 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메서드 의 두 번째 인수 는 문자열의 길이를 지정합니다.


답변

이용하십시오 string_agg!

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

MD5와 함께 이것을 사용하여 UUID도 생성하고 있습니다. 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

선행 번호는 해시 식별자입니다. 각각 고유 한 식별자가있는 여러 알고리즘을 사용할 수 있습니다.

  • md5 : $ 1 $
  • BF : $ 2a $ 06 $
  • des : 식별자 없음
  • xdes : _J9 ..

확장에 대한 추가 정보 :


편집하다

Evan Carrol이 지적했듯이 v9.4부터 다음을 사용할 수 있습니다. gen_random_uuid()

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