最近因為項目需要要寫預存程序,以前沒咋寫過,接觸到是接觸過,在軟通的時候接觸過,那是華為的項目那個幾個預存程序很大很複雜,也很亂,注釋也少,看了個大概。最近一個月,前後也寫了七八個簡單點的預存程序,也對預存程序有了一個簡單的認識,其實也不是很難,多查資料,多實踐。閑話不扯了,下面主要說一下遊標的組合使用,記錄下來即便以後長時間不用了忘記。
情境:有幾張表,現在根據業務要求要處理表b中的資料,但先要安照一個標準來處理是吧,這個標準又在表a中,a表中的標準有不是一條,現在需要安照a表的標準吧b表的資料都處理一邊。這個是業務。
思考:首先要安裝a表來處理的話,是不是要迴圈a表中的資料來處理那。肯定的,那就要先先一個遊標來控制a表迴圈了。接下來要根據a表的標準來分析b表的資料,那按照java的理解應該是在a表的迴圈中套一個迴圈來處理b表的資料,其實這裡也是一樣的,那就還需要一個遊標來控制整個裡層的迴圈了,到這就要考慮怎麼來嵌套遊標迴圈了,可以百度“oracle 嵌套遊標的使用”看看,這裡不記錄那些了,由於業務需要b表的資料量有比較大,a表的某一個標準也只是b表中的一部分資料,就是說但嵌套迴圈的時候還需要a表的中那條記錄的一些欄位資訊。這樣嵌套的時候考慮的就要多一點了,最後我選擇使用帶參數的遊標來實現,把需要的a表參數傳入b表中。
具體例子:
create or replace procedure P_SBZL_BLDY is --定義變數 v_xlbh SP_DATA_TQI.Xlbh%type; v_xingb SP_DATA_TQI.Xingb%type; v_qslc SP_DATA_TQI.tqilc%type; v_zzlc SP_DATA_TQI.tqilc%type; --定義“標準”的遊標 CURSOR bzs IS SELECT * from sp_dic_bldystandard b; ---定義要處理的具體資料的遊標 CURSOR sjs (vxlbh varchar2,vxingb varchar2,vqslc number,vzzlc number) IS select t.xlbh,t.xlm,t.xingb,t.xingbmc,t.tqisum,t.tqilc,t.dyid,p.rpcgs,p.ypcgs,p.cpcgs from SP_DATA_TQI t left join sp_sbzl_pcgs p on t.dyid = p.dyid where t.tqilc > vqslc and t.tqilc<vzzlc and t.xlbh = vxlbh and t.xingb = vxingb and p.jcny = to_char(sysdate,'yyyy-mm') and to_char(t.jcrq,'yyyy-mm')= to_char(sysdate,'yyyy-mm'); begin --清除當月資料 delete SP_SBZL_BLDYXX t where t.scny = to_char(sysdate,'yyyy-mm'); commit; --迴圈標準 for c in bzs loop begin v_xlbh := c.xlbh; v_xingb := c.xingb; v_qslc := c.qslc; v_zzlc := c.zzlc; --迴圈具體資料把相關參數傳入 for bhs in sjs(v_xlbh,v_xingb,v_qslc,v_zzlc) loop begin --一級 if bhs.tqisum<c.tqii and (bhs.ypcgs<c.cari) and (bhs.cpcgs<c.czypci) and (bhs.rpcgs<c.tcypci) then insert into SP_SBZL_BLDYXX values ( S_COMM_PK.NEXTVAL,bhs.xlbh,bhs.xlm,bhs.xingb,bhs.xingbmc,bhs.tqilc,bhs.tqisum,bhs.dyid,to_char(sysdate,'yyyy-mm'),'Ⅰ',c.id); commit; -- 2級 elsif bhs.tqisum>c.tqiii or (bhs.ypcgs>c.carii) or (bhs.cpcgs>c.czypcii) or (bhs.rpcgs>c.tcypcii) then --dbms_output.put_line('2'); insert into SP_SBZL_BLDYXX values ( S_COMM_PK.NEXTVAL,bhs.xlbh,bhs.xlm,bhs.xingb,bhs.xingbmc,bhs.tqilc,bhs.tqisum,bhs.dyid,to_char(sysdate,'yyyy-mm'),'Ⅱ',c.id); commit; --3級 elsif ((bhs.ypcgs>c.cariii1) and ( bhs.ypcgs>c.pciii1)) or ((bhs.ypcgs>c.cariii2) and (bhs.tqisum>c.tqiiii1)) or (bhs.tqisum>c.tqiiii2 and ( bhs.cpcgs>c.pciii2 or bhs.rpcgs>c.pciii2)) or (bhs.ypcgs>c.cariii3) then insert into SP_SBZL_BLDYXX values ( S_COMM_PK.NEXTVAL,bhs.xlbh,bhs.xlm,bhs.xingb,bhs.xingbmc,bhs.tqilc,bhs.tqisum,bhs.dyid,to_char(sysdate,'yyyy-mm'),'Ⅲ',c.id); commit; --4級 elsif ( bhs.tqisum>c.tqiiv and (bhs.ypcgs>c.cariv1) and ( (bhs.cpcgs > c.czypciv) or (bhs.rpcgs > c.tcypciv) ) ) or (bhs.ypcgs>c.cariv2) then insert into SP_SBZL_BLDYXX values ( S_COMM_PK.NEXTVAL,bhs.xlbh,bhs.xlm,bhs.xingb,bhs.xingbmc,bhs.tqilc,bhs.tqisum,bhs.dyid,to_char(sysdate,'yyyy-mm'),'Ⅳ',c.id); commit; end if; end; end loop; end; end loop; /* open cs; loop fetch cs into rec_test2.qslc, cur_test1; exit when cs%notfound; dbms_output.put_line(rec_test2.qslc); loop fetch cur_test1 into rec_test1; exit when cur_test1%notfound; dbms_output.put_line(rec_test1.tqilc); end loop; end loop; */ /*for c in cs loop BEGIN cursor zs is select * from SP_DATA_TQI t left join sp_sbzl_pcgs p on t.dyid = p.dyid where t.tqilc > c.qslc and t.tqilc<c.zzlc; for s in zs loop begin if s.tqiz<c.tqii then --i dbms_output.put_line('1'); elsif s.tqiz > c.tqii then dbms_output.put_line('2'); end; END; end loop;*/ end P_SBZL_BLDY;
遊標的一些具體寫法我就不記錄了,這裡的目的主要是以後遇到這類需要可以這樣來實現。