oracle存儲過程的應用案例(一)

需求:統計所有渠道底下的商戶總數

數據庫情況:

一張user表,通過userTpye來區別是渠道還是商戶,並且渠道是有多層級的。

一張機構表,每個機構有個orgCode字段來展示渠道層級,比如:1,12,135:表示135機構的上級是12,12的上級是1


當時庫裏有28000多條數據,公司是最高層級,底下有100多個渠道。

如果對每個渠道做數狀查詢計算底下商戶總數:

 s.org_id in (select c.id from sys_organization c start with c.id = #{code} connect by prior c.id = c.pid) 

這種數狀查詢需要檢索整個user表,100多渠道就需要檢索100多次,每次瀏覽2萬多條數據,計算量非常大。

所以當時我換一個做法,我把user表裏的用戶org_id對應的機構表orgCode取出來,那麼一共有28000個orgCode,然後通過java的for循環來進行統計,比如1,12,135出現的時候,對應的1渠道商戶數+1,對應的12渠道和135渠道的商戶數也+1.這樣只要做一次for循環就能把所有商戶的歸屬渠道統計出來。

這個看似可以解決問題,但是卻遇見了一個新的問題,就是我要把商戶的code集合從oracle中取出來時,2萬多條的數據集合從數據庫取到java服務器耗費了大量的時間。我用PL/SQL時也是,查詢條件可以0.2秒出結果,但是要展示所有的列卻花了十幾秒。我猜測這可能是由於數據庫需要展示數據時要進行I/O操作,這個操作的讀寫浪費了大量的時間。

所以我考慮在數據庫存儲過程裏面完成這個統計操作。下面是存儲過程全文,這個存儲過程裏運用了比較多的語法,所以我特地記下來。

create or replace procedure getAgentMerCountMap(orgId varchar2,codeIdList out varchar2,codeNumList out varchar2)
   as
   TYPE c_mer_acount IS RECORD
    (   id number,
        m_count number
    );
  ---根據自定義數據類型創建一個集合
  TYPE c_mer_acount_list IS TABLE OF c_mer_acount INDEX BY BINARY_INTEGER;
  ---集合對象
  mer_acount_list c_mer_acount_list;
  ---數據對象
  mer_acount c_mer_acount;
  ---計數器
  v_counter number;
  ---計算code長度
  code_len number;
  code_count number;
  m_code number;
  cursor c_test is
  select nuse.id,mer_name,nuse.createdatetime,sorg.code org_code from SYS_USER nuse,SYS_ORGANIZATION sorg where sorg.id=nuse.organization_id
      and nuse.ISDEFAULT = '1' and nuse.ISDEL = '0'
      and nuse.ORGANIZATION_ID in (select c.id from sys_organization c start with c.id = orgId connect by prior c.id = c.pid);
  c_t c_test%rowtype;


   begin


     DBMS_OUTPUT.ENABLE (buffer_size=>null);


      --不同code渠道的下屬商戶數量,key爲id,m_count爲人數。最後統計時要減一(減自身)
     for c_t in c_test loop


       --dbms_output.put_line( c_t.mer_name || '-0-' ||  c_t.org_code);


       --獲取code長度
       code_len:=LENGTH (c_t.org_code) - LENGTH (REPLACE (c_t.org_code, ',', ''))+1;


       --循環取出code並賦值給 mer_acount_list集合
       for code_count in 1..code_len loop
         --註釋:REGEXP_SUBSTR('變量','正則分隔符','從第幾個算起','取第幾個')
         m_code:=REGEXP_SUBSTR(c_t.org_code,'[^,]+',1,code_count);


         --如果code存在則value+1,否則新建該code渠道
         if mer_acount_list.exists(m_code) then
           mer_acount := mer_acount_list(m_code);
           mer_acount.m_count := mer_acount.m_count+1;
           mer_acount_list(m_code) := mer_acount;
         ELSE
           mer_acount.id:=m_code;
           --這裏實現了統計減一,將設置初始值爲0
           mer_acount.m_count := 0;
           mer_acount_list(m_code) := mer_acount;
         end if;
       end loop;


     end loop;


     codeIdList := '';
     codeNumList := '';
     v_counter := 0;
     code_count := 1;
     --將code集合用‘,’分隔封裝進返回參數codeIdList和codeNumList中。
     while v_counter<mer_acount_list.count loop
       if mer_acount_list.exists(code_count) then
         mer_acount := mer_acount_list(code_count);
         codeIdList := codeIdList || to_char(code_count) || ',';
         codeNumList := codeNumList || mer_acount.m_count || ',';
         v_counter := v_counter+1;
       end if;
       code_count := code_count+1;


     end loop;


     --dbms_output.put_line( codeIdList || '-0-' ||  codeNumList);
  end;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章