Oracle存儲過程遷移:循環語句修改爲JOIN一例(專有云:構造代碼表的新代碼)

*本人主要負責稅務專有云的架構支持,本例子使用環境爲專有云環境,ODPS版本爲1.0,比公有云版本低。*
總有同學提問,說我原來在oracle的存儲過程中的循環現在maxcompute不支持了,我的程序怎麼遷移。這個問題其實非常難以回答,一般來說99%的oracle的代碼都可以通過maxcompute的SQL和函數來替代,這個也包括一般的循環語句要解的問題。
下面這個例子就是一個例子,原來的存儲過程使用循環來爲多級組織機構代碼構建一個新的代碼表,因爲有多層級,所以使用了循環。
下面是原來存儲過程的代碼:
-----------------------使用循環進行更新,需要增加v_pid與v_id兩個輔助字段----------------------------
 update ZZJG_DM a set v_pid=pid;
 update ZZJG_DM a set v_id=id;
 update ZZJG_DM a set JBDM=null;
 update ZZJG_DM a set JCDM=1;
 set row_count = -1;
 while row_count != 0
 do
 update ZZJG_DM a,
 ZZJG_DM b, 
 (select id,pid,to_char(row_number() over (partition by pid order by id)) rn,
  row_number() over (partition by id order by pid) rm
  from ZZJG_DM) c
 set a.JBDM = concat(lpad(c.rn,4,'0'), nvl(a.JBDM,'')), 
  a.JCDM = a.JCDM+1,
  a.v_id=a.v_pid,
  a.v_pid=b.pid
 where a.v_pid = b.id and a.v_id = c.id and c.rm=1;
 set row_count=row_count(); 
 end while;
 
 update ZZJG_DM  set jbdm = '0000' where id = '00000000000';
乍一看挺複雜,好多年沒寫過存儲過程的我看着有點難過。但是當我們對齊一下需求和表數據,就會發現這個問題求解,其實並不會太難。maxcompute一定可以實現。
-------------------------------組織機構代碼表(ZZJG_DM)數據----------------------------------
id              pid                 jcdm      jbdm
00000000000                           1       0000
00000000010     00000000000           2       0001
00000000011     00000000000           2       0002
00000000012     00000000000           2       0003
00000100000     00000000000           2       0004
17900000000     00000000000           2       0005
17900000001     17900000000           3       0005 0001
17900000002     17900000000           3       0005 0002
17900000003     17900000001           4       0005 0001 0001     
17900000004     17900000001           4       0005 0001 0002
17900000005     17900000001           4       0005 0001 0003
17900000006     17900000002           4       0005 0002 0001     
17900000007     17900000002           4       0005 0002 0002     
17900000008     17900000004           5       0005 0001 0002 0001     
17900000009     17900000004           5       0005 0001 0002 0002
17900000011     17900000009           6       0005 0001 0002 0002 0001
17900000012     17900000009           6       0005 0001 0002 0002 0002
17900000013     17900000012           7       0005 0001 0002 0002 0002 0001
17900000014     17900000012           7       0005 0001 0002 0002 0002 0002
17900000015     17900000012           7       0005 0001 0002 0002 0002 0003
17900000016     17900000012           7       0005 0001 0002 0002 0002 0004

----------------------------------需求-------------------------------------------
根據id 與 pid 上下級關係,逐層更新jcdm 與 jbdm。
jcdm:級別代碼,節點所在層級。
jbdm:按pid分組的組內排序序號(不足4位補齊4位) 左邊拼接上級的jbdm。
組織機構代碼表分7級,原來有一套代碼,現在這個程序需要重新構造一個代碼結構。而且,需要生成一個表示代碼所在層級的列。需求就是jcdm/jbdm這兩列。我先從原來存儲過程所在的數據庫平臺,瞭解數據需求和求解結果。理解了這個代碼的輸入輸出,接下來就是求解。 
jcdm就是代碼所在的級別。因爲原來代碼表結構是(級別代碼-上級代碼)結構,所以,我只要把代碼表自關聯7次,能關聯到第幾級代碼就是第幾個級別。
jbdm是新構造的代碼表,我查看明細結果數據後發現其實就是一個按照上級代碼分組,按照機構代碼排序的序號值,標準化到了4位長度。所以,按照上級代碼分組再排序的序號最後拼接在一起,就是我新構造的代碼表了。
前後大概折騰了2個小時,代碼基本完成。
select id
,pid
,new_jcdm as jcdm
,nrank 
,nrank2
,nrank3
,nrank4
,nrank5
,nrank6
,nrank7
,case when new_jcdm=1 then '0000'
    when new_jcdm=2 then nrank
    when new_jcdm=3 then concat(nrank2,nrank)
    when new_jcdm=4 then concat(nrank3,nrank2,nrank)
    when new_jcdm=5 then concat(nrank4,nrank3,nrank2,nrank)
    when new_jcdm=6 then concat(nrank5,nrank4,nrank3,nrank2,nrank)
    when new_jcdm=7 then concat(nrank6,nrank5,nrank4,nrank3,nrank2,nrank)
end as jbdm
from(
     SELECT id,pid
            ,substr(concat('0000',to_char(nrank )),length(to_char(nrank ))+1,4) as nrank 
            ,substr(concat('0000',to_char(nrank2)),length(to_char(nrank2))+1,4) as nrank2
            ,substr(concat('0000',to_char(nrank3)),length(to_char(nrank3))+1,4) as nrank3
            ,substr(concat('0000',to_char(nrank4)),length(to_char(nrank4))+1,4) as nrank4
            ,substr(concat('0000',to_char(nrank5)),length(to_char(nrank5))+1,4) as nrank5
            ,substr(concat('0000',to_char(nrank6)),length(to_char(nrank6))+1,4) as nrank6
            ,substr(concat('0000',to_char(nrank7)),length(to_char(nrank7))+1,4) as nrank7
            ,new_jcdm
     from(
             SELECT /*+ mapjoin(t2,t3,t4,t5,t6,t7)*/ t1.id
            ,t1.pid
            ,row_number() over(partition by t1.pid order by t1.id) as nrank
            ,t2.nrank as nrank2
            ,t3.nrank as nrank3
            ,t4.nrank as nrank4
            ,t5.nrank as nrank5
            ,t6.nrank as nrank6
            ,t7.nrank as nrank7
            ,t2.id as id2
            ,t3.id as id3
            ,t4.id as id4
            ,t5.id as id5
            ,t6.id as id6
            ,t7.id as id7
            ,case when t7.id is not null then 7
                  when t6.id is not null then 6
                  when t5.id is not null then 5
                  when t4.id is not null then 4
                  when t3.id is not null then 3
                  when t2.id is not null then 2
             else 1 end as new_jcdm
             FROM ZZJG_DM t1
                 left outer join(select id,pid,row_number() over(partition by pid order by id) as nrank from ZZJG_DM where yfq='201812') t2 on t1.pid=t2.id
                 left outer join(select id,pid,row_number() over(partition by pid order by id) as nrank from ZZJG_DM where yfq='201812') t3 on t2.pid=t3.id
                 left outer join(select id,pid,row_number() over(partition by pid order by id) as nrank from ZZJG_DM where yfq='201812') t4 on t3.pid=t4.id
                 left outer join(select id,pid,row_number() over(partition by pid order by id) as nrank from ZZJG_DM where yfq='201812') t5 on t4.pid=t5.id
                 left outer join(select id,pid,row_number() over(partition by pid order by id) as nrank from ZZJG_DM where yfq='201812') t6 on t5.pid=t6.id
                 left outer join(select id,pid,row_number() over(partition by pid order by id) as nrank from ZZJG_DM where yfq='201812') t7 on t6.pid=t7.id
            where t1.yfq='201812'
    )t
)tt
order by id;
結果就如上,其實就是普通的代碼表處理方法,有幾級就JOIN幾次就可以了。因爲一般機構代碼的層次不會隨便更新,所以,這個方法是可以在實際中使用的。循環可以適配級別的變化,但是在解決這個問題時實際上是沒必要非寫出循環的。
遷移程序時,遇到問題,一定不要把問題限制在這個方法不支持,我就不會做了。而是要看具體是什麼問題,一般一個需求是有多種解法的。

-- 暮角 15901445705 update at 20181224

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