1. 程式人生 > >oracle生成不重複隨機數

oracle生成不重複隨機數

1.建立FUNCTION fn_ifrandom(其中用到遞迴)

CREATE OR REPLACE FUNCTION fn_ifrandom (tmpallrandom IN clob,tmprandom IN VARCHAR2,allcount in number)
 RETURN varchar2
IS  --生成不重複的隨機數
  randomchar varchar2(5);  --最終返回的不重複的隨機數
  randomchar1 varchar2(5);
  ifrandom number;  --迴圈生成隨機數時,判斷是否是重複隨機數
BEGIN
     --判斷是否是重複隨機數,是則ifrandom>0,否則ifrandom=0
    select instr(tmpallrandom,tmprandom,1,1) into ifrandom from dual;
     if ifrandom>0 then --重複了,再生成
         select to_char(round(dbms_random.value(1,allcount))) into randomchar1 from dual;
         randomchar := fn_ifrandom(tmpallrandom,randomchar1,allcount);
     else
         randomchar := tmprandom;
     end if;
  RETURN randomchar;
END fn_ifrandom;


2.儲存過程呼叫:

CREATE OR REPLACE PROCEDURE p_main2_mx(kouchucnt in number,allcount in number)
as
       tmprandom varchar2(5);  --隨機數,(最大20000)
       tmpallrandom varchar2(32767);   --拼接好的不重複隨機數,滿足條件後寫入tmpclob並清空
       tmpclob clob; --tmpallrandom拼接長度超過32767後,拼入此變數,後面都用此變數
       v_cnt number(5);  --拼接clob計數時用
begin
      if kouchucnt is not null or kouchucnt<>0 then  
        --生成拼接的隨機數,範圍為1-allcount
        for i in 1 ..kouchucnt loop
                --生成隨機數
                select to_char(round(dbms_random.value(1,allcount))) into tmprandom from dual;
                tmprandom := fn_ifrandom(tmpclob||tmpallrandom,tmprandom,allcount);
                tmpallrandom := tmpallrandom||tmprandom||',';
                v_cnt := v_cnt+1;  
                if v_cnt = 5461 then  --5461 = 32767 / 6
                     v_cnt := 0;  
                     tmpclob := tmpclob||tmpallrandom;
                     tmpallrandom := '';
               end if;
       end loop;     
       if v_cnt <>0 then  
           tmpclob := tmpclob || tmpallrandom;  
       end if; 
       --因為拼接的所有tmpallrandom最後是,'   所以使用時要去掉後2位,並且在第一位拼一個單引號
        tmpclob :=replace(tmpclob,',,',',');
        tmpclob :=substr(tmpclob,1,length(tmpclob)-1);
       -----------------開始(下面將拼好的隨機數拆分了逗號變成一個table,where in table就沒有in 1000個的限制)
       for ifbmd_record in (select id,mobilecode from T_BUSI_PRESEND_MX where mainid=main2id and rowid in (
            select t.row_id from(
            select rownum rn,rowid row_id from t_busi_presend_mx where mainid=main2id
            ) t where t.rn in (SELECT  a.column_value cva FROM TABLE( fn_split(tmpclob,',') ) a )
          )
        ) loop
        --......
        end loop;
end ;


知識點:

1.拼接長度超過32767時,就應該將大varchar2串拼到clob串再重新開始拼接varchar2串。

2.where in條件中有1000個的限制,如果in一個table,就沒有此限制。應該先將要in的條件用逗號隔開然後用自寫的split把他分成一個臨時表。