One approach would be to create a custom aggregate function that mimics the behavior of the listagg function. Here is an example:
Our custom 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 longer than 4000, you can use the CLOB type datatype instead of varchar2 . Now you can create an additional function that will generate a random string for you using this str_agg aggregate function. Since 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
source share