ger*_*rsh 98 random postgresql
我想制作一个随机字符串,用于使用PostgreSQL进行会话验证.我知道我可以得到一个随机数SELECT random()
,所以我试过SELECT md5(random())
,但这不起作用.我怎样才能做到这一点?
Pet*_*aut 222
您可以像这样修复您的初始尝试:
SELECT md5(random()::text);
Run Code Online (Sandbox Code Playgroud)
比其他一些建议简单得多.:-)
Szy*_*ski 72
我建议这个简单的解决方案:
这是一个非常简单的函数,它返回给定长度的随机字符串:
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;
Run Code Online (Sandbox Code Playgroud)
用法:
select random_string(15);
Run Code Online (Sandbox Code Playgroud)
示例输出:
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)
Run Code Online (Sandbox Code Playgroud)
gro*_*urk 29
在Marcin的解决方案的基础上,您可以使用任意字母表(在这种情况下,所有62个ASCII字母数字字符):
SELECT array_to_string(array
(
select substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', trunc(random() * 62)::integer + 1, 1)
FROM generate_series(1, 12)), '');
Run Code Online (Sandbox Code Playgroud)
Eva*_*oll 19
您可以从UUID获得128位随机数.这是在现代PostgreSQL中完成工作的方法.
CREATE EXTENSION pgcrypto;
SELECT gen_random_uuid();
gen_random_uuid
--------------------------------------
202ed325-b8b1-477f-8494-02475973a28f
Run Code Online (Sandbox Code Playgroud)
数据类型uuid存储RFC 4122,ISO/IEC 9834-8:2005和相关标准定义的通用唯一标识符(UUID).(有些系统将此数据类型称为全局唯一标识符,或称为GUID.)此标识符是128位数量,由选择的算法生成,以使其他人不太可能生成相同的标识符在已知的宇宙中使用相同的算法.因此,对于分布式系统,这些标识符提供了比序列生成器更好的唯一性保证,序列生成器在单个数据库中是唯一的.
与UUID的碰撞有多罕见,或者是可猜测的?假设它们是随机的,
需要生成大约100万亿版本的4个UUID才能获得单个重复的十亿分之一("冲突").只有在生成261个UUID(2.3 x 1018或2.3 quintillion)之后,一次碰撞的几率才会上升到50%.将这些数字与数据库相关联,并考虑到版本4 UUID冲突的概率是否可忽略的问题,请考虑包含2.3个quintillion版本4 UUID的文件,其中50%的可能性包含一个UUID冲突.它假设没有其他数据或开销,大小为36艾字节,是目前存在的最大数据库的数千倍,大约为千兆字节.以每秒生成10亿UUID的速率,生成文件的UUID需要73年.假设没有备份或冗余,它还需要大约360万个10TB硬盘或磁带盒来存储它.以典型的"磁盘到缓冲"传输速率(每秒1千兆位)读取文件,单个处理器需要3000多年.由于驱动器的不可恢复读取错误率是每1018位读取1位,充其量,当文件包含大约1020位时,仅从端到端读取文件一次将导致至少大约100倍的错误读取UUID而不是重复.毫无疑问,存储,网络,电源和其他硬件和软件错误比UUID重复问题的频率高出数千倍.- 来源维基百科
综上所述,
gen_random_uuid()
是128位随机存储在128位(2**128组合)中.0垃圾.random()
在PostgreSQL中只生成52位随机数(2**52种组合).md5()
存储为UUID的是128位,但它只能与其输入一样随机(如果使用则为52位random()
)md5()
作为文本存储的是288位,但它只能与其输入一样随机(如果使用则为52位random()
) - 超过UUID大小的两倍和随机性的一小部分)md5()
作为哈希,可以如此优化,以至于它不能有效地做很多事情.text
和varchar
等其存储为varlena
具有用于字符串的长度的开销.Mar*_*ski 14
我最近玩的是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
Run Code Online (Sandbox Code Playgroud)
方法的第二个参数generate_series
指示字符串的长度.
Jef*_*ave 11
虽然默认情况下不活动,但您可以激活其中一个核心扩展:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
Run Code Online (Sandbox Code Playgroud)
然后你的语句变成对gen_salt()的简单调用,它生成一个随机字符串:
select gen_salt('md5') from generate_series(1,4);
gen_salt
-----------
$1$M.QRlF4U
$1$cv7bNJDM
$1$av34779p
$1$ZQkrCXHD
Run Code Online (Sandbox Code Playgroud)
前导号码是散列标识符.有几种算法可用,每种都有自己的标识符:
有关扩展的更多信息:
编辑
如Evan Carrol所示,从v9.4开始,你可以使用 gen_random_uuid()
http://www.postgresql.org/docs/9.4/static/pgcrypto.html
And*_*lfe 11
请使用string_agg
!
SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '')
FROM generate_series(1, 45);
Run Code Online (Sandbox Code Playgroud)
我正在使用MD5来生成UUID.我只想要一个比一个random ()
整数更多位的随机值.
@Kavius 推荐使用pgcrypto
,而不是gen_salt
,那么gen_random_bytes
呢?而sha512
不是md5
呢?
create extension if not exists pgcrypto;
select digest(gen_random_bytes(1024), 'sha512');
Run Code Online (Sandbox Code Playgroud)
文档:
F.25.5。随机数据函数
gen_random_bytes(count integer) 返回字节
返回计数加密强随机字节。一次最多可以提取 1024 个字节。这是为了避免耗尽随机生成器池。
create extension if not exists pgcrypto;
Run Code Online (Sandbox Code Playgroud)
然后
SELECT encode(gen_random_bytes(20),'base64')
Run Code Online (Sandbox Code Playgroud)
甚至
SELECT encode(gen_random_bytes(20),'hex')
Run Code Online (Sandbox Code Playgroud)
这适用于 20 字节 = 160 位随机性(例如 sha1)。
INTEGER 参数定义字符串的长度。保证以相等的概率覆盖所有 62 个字母数字字符(与 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;
Run Code Online (Sandbox Code Playgroud)
我不认为你正在寻找一个随机的字符串本身.会话验证所需的是一个保证唯一的字符串.您是否存储会话验证信息以供审核?在这种情况下,您需要字符串在会话之间是唯一的.我知道两种相当简单的方法:
UUID 凭借其生成算法保证是唯一的; 有效是非常不可能的,你会不会产生任何机器上有两个相同的数字,在任何时候,曾(注意,这是不是随机字符串,它比的UUID小得多的周期性更强).
您需要加载uuid-ossp扩展名才能使用UUID.安装完成后,在SELECT,INSERT或UPDATE调用中调用任何可用的uuid_generate_vXXX()函数.uuid类型是一个16字节的数字,但它也有一个字符串表示.
归档时间: |
|
查看次数: |
69868 次 |
最近记录: |