Как сгенерировать случайную строку из фиксированного набора символов?
Как сгенерировать случайную строку в PL/SQL из фиксированного набора символов?
Например, требуется сгенерировать буквенно-цифровую строку длиной 10, исключающую определенные символы и цифры, такие как I, O, 0 и т.д.
Не смог найти способ вызвать DBMS_RANDOM.STRING() с требуемым набором символов. Параметром можно передать только класс символов:
select DBMS_RANDOM.STRING ('x', 10) rnd
from dual;
RND
----------
PTPYOGY70T
Есть ли встроенный способ сделать это в PL/SQl?
Свободный перевод вопроса Generate Random String from fixed set of characters от участника @user931518
Ответы (2 шт):
Можно написать самому функцию, которая принимает определенный набор символов, смешает их в случайном порядке и вернет результат.
Вот пример такой функции:
create or replace function RandomString(p_Characters varchar2,
p_length number) return varchar2 is
l_res varchar2(256);
begin
select substr(listagg(substr(p_Characters, level, 1)) within group (
order by dbms_random.value), 1, p_length)
into l_res
from dual connect by level <= length(p_Characters);
return l_res;
end;
И как ею пользоватся:
select randomstring('1234567abcdefg', 10) res
from dual connect by level <= 10
/
RES
----------
d17cg4e35a
b7e1f3cd46
defba7g51c
431gcd5fa7
43bgc57ad2
4fe26ad3c5
32e176ca4b
25df6c34e1
52edg6f4ba
3abf645g21
10 rows selected.
Свободный перевод ответа от участника @Nick Krasnov
Решение без запроса в функции:
create or replace function randomize (chars varchar2, len int) return varchar2 is
val varchar2 (32767);
begin
for i in 1..len loop
val := val||substr (chars, round (dbms_random.value (1, length(chars))), 1);
end loop;
return val;
end;
/
Если предполагается преимущественно использовать в SQL запросе, то эффективней будет, определить функцию прямо в запросе:
with
function randomize (chars varchar2, len int) return varchar2 is
val varchar2 (32767);
begin
for i in 1..len loop
val := val||substr (chars, round (dbms_random.value (1, length(chars))), 1);
end loop;
return val;
end;
select randomize (trim (column_value), 10) rnd
from xmlTable ('"123abcdef", "09zyxwvu"')
cross join (select 0 from dual connect by level<=2);
RND
----------
feede2c32b
vxyv9wwz90
cafdae2a3b
0y9zzz9wv9
Оба примера воспроизводятся на db<>fiddle.