我正在尝试使用带有一些受限字母的 PL/SQL 生成随机字符串,因为我想避免使用 O、o、0 等字母。我听说可以使用 oracle 11g 中提供的 listagg 函数来完成此任务。但是我想使用 Oracle 9i 来实现这一点,因为我们在我们的环境中使用它。任何建议将不胜感激。
问问题
3691 次
4 回答
3
尝试使用DBMS_RANDOM包生成随机字符串。
例如:dbms_random.string('x',10)
给出长度为 10 的大写字母数字字符串。
但是你不能排除特定的字符。您必须使用TRANSLATE
或REPLACE
函数来删除不需要的字符。
于 2013-06-05T07:40:01.087 回答
2
其中一种方法是创建一个用户定义的聚合函数来模仿listagg
函数的行为。这是一个例子:
我们用户定义的聚合函数:
SQL> create or replace type stragg as object ( 2 3 str varchar2(4000), 4 5 static function ODCIAggregateInitialize(sctx in out stragg) 6 return number, 7 8 member function ODCIAggregateIterate (self in out stragg, 9 value in varchar2 ) 10 return number, 11 12 member function ODCIAggregateTerminate (self in stragg , 13 return_value out varchar2, 14 flags in number ) 15 return number, 16 17 member function ODCIAggregateMerge(self in out stragg, 18 ctx2 in stragg ) 19 return number 20 ) 21 / Type created SQL> create or replace type body stragg is 2 3 static function ODCIAggregateInitialize(sctx in out stragg) 4 return number is 5 begin 6 sctx := stragg(null); 7 return ODCIConst.Success; 8 end; 9 10 member function ODCIAggregateIterate( 11 self in out stragg, value in varchar2) 12 return number is 13 begin 14 str := str || value; 15 return ODCIConst.Success; 16 end; 17 18 member function ODCIAggregateTerminate(self in stragg, 19 return_value out varchar2, flags in number) return number is 20 begin 21 return_value := str; 22 return ODCIConst.Success; 23 end; 24 25 member function ODCIAggregateMerge(self in out stragg, 26 ctx2 in stragg) return number is 27 begin 28 str := str || ctx2.str; 29 return ODCIConst.Success; 30 end; 31 end; 32 / Type body created SQL> create or replace function str_agg (input varchar2) return varchar2 2 parallel_enable aggregate using stragg; 3 / Function created
如果您计划使用长度超过 4000 的字符串,则可以使用CLOB
datatype 而不是varchar2
. str_agg
现在,您可以创建一个附加函数,该函数将使用该聚合函数为您生成一个随机字符串。由于您想从结果字符串中排除某些字符,我认为最好提供一组字符,从中生成所需的字符串。
SQL> create or replace function Str_gen(p_CharSet varchar2, p_length number)
2 return varchar2
3 is
4 l_res_str varchar2(4000);
5 begin
6 select str_agg(symbol)
7 into l_res_str
8 from ( select substr(p_CharSet,
9 dbms_random.value(1, length(p_charset)), 1) as symbol
10 from dual
11 connect by level <= p_length
12 order by dbms_random.value
13 );
14
15 return l_res_str;
16 end;
17 /
Function created
以下是它的工作原理:
SQL> select str_gen('abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789',11) as res
2 from dual
3 connect by level <= 11
4 /
RES
--------------------------------------------------------------------------------
NBG5jK6G46G
fSrzmyq7ZLE
vdGE1dRXlah
1D2IsI54qzD
PhktBAh5rXu
JtRsarxFNiV
1sUGFpwmypQ
7giwfdV4I7s
I2WMhKzxvc2
NZpngmrq1gM
rFuZ8gSUDgL
11 rows selected
于 2013-06-05T07:30:56.027 回答
2
扯掉 ABCade 的答案(它离原版有点太远了,无法保留评论):
select xmlagg(xmlelement("r", ch)).extract('//text()').getstringval()
from
(
select distinct first_value(ch) over (partition by lower(ch)) as ch
from (
select substr('abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789',
level, 1) as ch
from dual
connect by level <= 59
order by dbms_random.value
)
where rownum <= dbms_random.value(10,13)
);
内部选择是将值字符串中的每个字符按随机顺序排列;下一个级别使用first_value()
anddistinct
选择它首先看到的大写和小写对(a
/ A
),这样即使忽略大小写也不会重复;然后限制为前 10、11 或 12 行(不同的);最后它使用相同的xmlagg
调用将这些行转换为单个字符串。
于 2013-06-05T11:05:46.223 回答
1
create or replace function str_gen
( len in number)
return varchar2
as
str varchar2(4000);
valid_chars constant varchar2(50) := 'abcdefghijklmnpqrstuvwxyz';
begin
for i in 1..len
loop
str := str || substr( valid_chars, dbms_random.value(1, length(valid_chars)), 1);
end loop;
return str;
end;
/
不直接重复相同的字母
create or replace function str_gen
( len in number)
return varchar2
as
str varchar2(4000);
valid_chars constant varchar2(50) := 'abcdefghijklmnpqrstuvwxyz';
last_char varchar2(1);
new_char varchar2(1);
chars_len NUMBER;
num NUMBER;
begin
chars_len := length(valid_chars);
num := 0;
if len > 0 then
loop
new_char := substr( valid_chars, dbms_random.value(1, chars_len ), 1);
if num = 0 then
str := new_char;
num := num +1;
elsif new_char != last_char
then
str := str || new_char;
num := num +1;
end if;
last_char := new_char;
exit when num = len;
end loop;
end if;
return str;
end;
/
select str_gen(11) from dual;
于 2013-06-05T08:22:58.670 回答