我正在使用这个 SQL 查询在 PostgreSQL 中生成随机值
chr(ascii('B') + (random() * 25)::integer)
如何在同一查询中生成一个15个字符的随机字符串?
我正在使用这个 SQL 查询在 PostgreSQL 中生成随机值
chr(ascii('B') + (random() * 25)::integer)
如何在同一查询中生成一个15个字符的随机字符串?
另一个非常易于阅读的解决方案(性能应该是合理的,但没有进行基准测试):
select substr(md5(random()::text), 0, 25);
如果您喜欢,可以使用大写字母:
select upper(substr(md5(random()::text), 0, 25));
这是我的贡献
postgres=# SELECT array_to_string(array(select substr('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',((random()*(36-1)+1)::integer),1) from generate_series(1,50)),'');
array_to_string
----------------------------------------------------
4XOS6TQG5JORLF3D1RPXUWR2FQKON9HIXV0UGH0CQFT1LN5D4L
(1 row)
它让您可以指定允许的字符集和字符串的长度。
(random()*(36-1)+1)::int
会将1到36之间的随机数四舍五入为最接近的整数。这意味着第一个和最后一个字符的频率约为其余字符的一半。您可以使用floor(random()*36)::int+1
来代替。 - undefined这将会给你一个长度为15的随机词,由源值常量中配置的字母组成。
select
string_agg(substr(characters, (random() * length(characters) + 1)::integer, 1), '') as random_word
from (values('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')) as symbols(characters)
-- length of word
join generate_series(1, 15) on 1 = 1
编辑:要获取多个随机单词,您可以使用以下方法:
with symbols(characters) as (VALUES ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'))
select string_agg(substr(characters, (random() * length(characters) + 1) :: INTEGER, 1), '')
from symbols
join generate_series(1,8) as word(chr_idx) on 1 = 1 -- word length
join generate_series(1,10000) as words(idx) on 1 = 1 -- # of words
group by idx
substr
的调用可能会返回一个空字符串,这将导致返回的值少于8个字符。只是需要注意一下,但仍然是一个好的解决方案。 - François Beausoleil您可以通过单个查询完成此操作,但是如果您希望每个字符根据范围分开,则上述解决方案是可行的。
SELECT array_to_string(ARRAY(
SELECT chr((ascii('B') + round(random() * 25)) :: integer)
FROM generate_series(1,15)),
'');
我使用这个方法来生成随机字符串...
如果您不介意连接线并启用了uuid扩展...
select substr(uuid_generate_v4()::text,1,15);
select concat('name-', substr(uuid_generate_v4()::text,1,10)) as name;
例如,name-91fc72dc-d
否则,请使用来自@fncomp的优秀md5示例
注:要启用uuid扩展名
create extension if not exists "uuid-ossp";
gen_random_uuid()
,它是自Postgres 13+以来的核心功能,无需扩展程序,例如:SELECT substr(gen_random_uuid()::text, 1, 8)
。 - kino1函数
:CREATE OR REPLACE FUNCTION random_string(int) RETURNS TEXT as $$
SELECT substr(md5(random()::text), 0, $1+1);
$$ language sql;
这个函数名叫做random_string
,它需要一个字符串长度
作为参数。
函数
select random_string(6);
insert into users values(nextval('users_sequence'), random_string(6), random_string(6));
do $$
begin
for i in 1..100 loop
insert into users values(nextval('users_sequence'), random_string(6), random_string(6));
end loop;
end;
$$;
等等。
我尝试使用 @Bennit 的解决方案,但注意到其中存在一些缺陷。随机部分的计算有点错误,导致结果有误:最终长度比期望的要短。
[快速查看了 @lyndon-s 的版本 - 很可能也存在同样的缺点]
因此,这里是更新后的 @bennit 版本:
select
string_agg(substr(characters, (random() * length(characters) + 0.5)::integer, 1), '') as random_word
from (values('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')) as symbols(characters)
-- length of word
join generate_series(1, 15) on 1 = 1
这里是需要进行更改的演示:
更正后:
select n,count(*) from (
select (random() * 10 + 0.5)::integer as n from dbfiles
join generate_series(1, 100000) on 1 = 1
) as s group by n
order by 1;
Original:
select n,count(*) from (
select (random() * 10 + 1)::integer as n from dbfiles
join generate_series(1, 100000) on 1 = 1
) as s group by n
order by 1;
select (chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer) ||
chr(ascii('B') + (random() * 25)::integer)
) as Random15
这是我的PL/pgSQL实现:
create or replace function random_string (
str_length integer, lang varchar(2) default 'en',
w_dig boolean default true, w_punct boolean default true,
w_space boolean default false, w_newline boolean default false
)
returns text
language plpgsql
as $function$
declare
chars_eng text[] := '{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}';
chars_rus text[] := '{А,Б,В,Г,Д,Е,Ё,Ж,З,И,Й,К,Л,М,Н,О,П,Р,С,Т,У,Ф,Х,Ц,Ч,Ш,Щ,Ъ,Ы,Ь,Э,Ю,Я,а,б,в,г,д,е,ё,ж,з,и,й,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ъ,ы,ь,э,ю,я}';
chars_dig text[] := '{}';
chars_punct text[] := '{}';
chars_space text[] := '{}';
chars_newline text[] := '{}';
chars_final text[] := '{}';
result text := '';
i integer := 0;
begin
-- checking string length arg
if str_length < 0 then
raise exception 'Length of string cannot be a negative value';
end if;
-- checking chars selection
if w_dig = true then
chars_dig := '{0,1,2,3,4,5,6,7,8,9}';
end if;
if w_punct = true then
chars_punct := string_to_array(E'!d"d#d$d%d&d\'d(d)d*d+d,d-d.d/d:d;d<d=d>d?d@d[d\\d]d^d_d`d{d|d}d~','d');
end if;
if w_space = true then
chars_space := string_to_array(' ',',');
end if;
if w_newline = true then
chars_newline := string_to_array(E'\r\n',',');
end if;
-- checking language selection
if lang = 'en' then
chars_final := chars_eng||chars_dig||chars_punct||chars_space||chars_newline;
elsif lang = 'ru' then
chars_final := chars_rus||chars_dig||chars_punct||chars_space||chars_newline;
else
raise exception 'Characters set for that language is not defined';
end if;
-- filling the string
for i in 1..str_length loop
result := result || chars_final[1 + round(random() * (array_length(chars_final, 1) - 1))];
end loop;
-- trimming extra symbols that may appear from /r/n usage
if length(result) > str_length then
result := left(result, str_length);
end if;
-- getting the result
return result;
end;
$function$ ;
在这里提供我的意见。我需要随机字符串来进行一些基准测试,因此对我来说真正重要的是这些字符串彼此之间是唯一的。
select rpad(generate_series::varchar, 1000, 'hi') from generate_series(1,10);
rpad - 右侧填充至长度(1000),填充内容为'hi' generate_series(1,10) - 生成10行
结合上面的答案,你也可以这样做:
select rpad(generate_series::varchar, 1000, md5(random()::text)) from generate_series(1,10)
这将确保您有200个字符,或任何所需的长度。