One of the approaches would be creating a user-defined aggregate function that mimic listagg
function's behavior. Here is an example:
Our user-defined aggregate function:
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
If you plan to work with strings that are more then 4000 in length you can use CLOB
datatype instead of varchar2
. Now, you can create an additional function that will generate a random string for you using that str_agg
aggregate function. As you want to exclude some characters from the resulting string, I think it would be better to provide a set of characters from which the desired string will be generated.
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
And here is how it works:
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