使用受限字母在PL / SQL(oracle 9i)中生成随机字符串

时间:2013-06-05 06:31:58

标签: oracle random oracle9i

我正在尝试使用带有一些限制字母的PL / SQL生成随机字符串,因为我想避免使用O,o,0等字母。我听说使用listagg函数可以实现此任务oracle 11g。但我希望使用Oracle 9i实现这一点,因为我们在我们的环境中使用它。任何建议将不胜感激。

4 个答案:

答案 0 :(得分:2)

其中一种方法是创建一个模仿listagg函数行为的用户定义聚合函数。这是一个例子:

  1. 我们的用户定义聚合函数:

     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
    
  2. 如果您计划使用长度超过4000的字符串,则可以使用CLOB数据类型而不是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
    

答案 1 :(得分:2)

尝试使用DBMS_RANDOM包生成随机字符串。

Ex:dbms_random.string('x',10)提供长度为10的大写字母数字字符串。

但你不能排除特定的字符。您必须使用TRANSLATEREPLACE功能删除不需要的字符。

答案 2 :(得分:2)

重复A.B.Cade的回答(它与原版有点太远,无法继续发表评论):

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)
);

SQL Fiddle

内部选择将值中的每个字符放入随机顺序;下一级使用first_value()distinct来选择它首先看到的大写和小写对(a / A),这样你就不会重复甚至忽略大小写;然后限制在前10,11或12(不同)行;最后它使用相同的xmlagg调用将这些行转换为单个字符串。

答案 3 :(得分: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;