儲存過程+巢狀遊標結合使用的例項
阿新 • • 發佈:2019-01-28
上週接了一個新任務——寫儲存過程,我以前可不知道這玩意怎麼寫,上週用了一個星期琢磨了一下然後終於給弄出來了,資料庫用的是Oracle,需求是說要每天定時去處理大批量的資料,用儲存過程處理好了存在中間表裡面,然後專案平臺就直接取中間表的資料就OK,因為目前而言我們是以XX平臺為基礎的二次開發,很多開發具有侷限性,對於大量的資料處理全都是原生sql多表聯查各種複雜查詢出來,效率特別低,速度特慢,所以就有了這麼一個任務了。個人建議還是使用PL/SQl比較方便。我首先就是寫一個入口,所有其他儲存過程呼叫都從這個入口開始:
第一步:寫一個儲存過程入口
我這邊是執行所有ETL開頭的儲存過程
create or replace procedure START_ETL is cursor procs is select object_name as pn from user_procedures where object_name like 'ETL%'; proc procs%rowtype; begin for proc in procs loop execute immediate 'begin '||proc.pn||'; end;'; -- dbms_output.put_line(proc.pn); end loop; end START_ETL;
第二步:寫一個定時器
begin
sys.dbms_job.submit(job => :job,
what => 'begin
start_etl;
end;',
next_date => to_date('30-10-2017 17:10:00', 'dd-mm-yyyy hh24:mi:ss'),
interval => 'sysdate+1/24/3');
commit;
end;
/
我這裡是每隔sysdate+1/24/3也就是20分鐘執行一次的,這個定時器就是在DBMS_Jobs下面建立的
第三步:編寫處理資料的儲存過程
基本上就可以了,我是用了兩層遊標巢狀遍歷,把執行過程情況寫入日誌表中,這樣多個儲存過程執行的時候方便定位問題所在,另外,寫完儲存過程之後最好就是先除錯一下,選中儲存過程右擊會出現test測試,點選進入除錯頁面,具體怎麼除錯可以百度一下都有的,謝謝
create or replace procedure ETL_NON_OIL_SALES_PROC is seq_log integer; -- 日誌表序列 seq_theme_log integer;--主題日誌序列 seq_theme integer; --主題表序列 stationcode varchar2(8); --油站編號 stationname varchar2(30); --油站名稱 --定義主題遊標 cursor etl_theme_cur is select * from (SELECT T4.SITE_CODE AS STATION_CODE, T4.STATION_NAME, T4.DEPTID, T4.DEPTNAME, T4.ITEMNAME, T4.ITEMID, T4.TOTAL AS SALES_AMOUNT, T4.QTY, T4.DAY_BATCH_ID, T4.DAY_BATCH_DATE, S.ORG_CODE AS COMPANYID, S.ORG_ABBR AS COMPANY from ...........此處sql太長,省略後續部分); --定義遊標,該遊標指向查詢結果 rowresult etl_theme_cur%rowtype; --宣告行型別變數rowresult --定義油站編號的遊標 cursor etl_org_cur is select site_code,org_abbr from sys_org where org_type='Z'; rowres etl_org_cur%rowtype; begin select etl_seq.nextval into seq_log from dual; insert into etl_proc_log values(seq_log,sysdate,null,'ETL_NON_OIL_SALES_PROC',null); --儲存過程執行開始日誌 open etl_org_cur; --開啟油站遊標 loop fetch etl_org_cur into rowres; --取出油站遊標的值放入行型別中 exit when etl_org_cur%notfound; select rowres.site_code into stationcode from dual; --給變數賦值 select rowres.org_abbr into stationname from dual; select etl_seq.nextval into seq_theme_log from dual; --給主題日誌序列賦值 insert into etl_theme_log values(seq_theme_log,'ETL_NON_OIL_SALES',sysdate,null,rowres.site_code,rowres.org_abbr,null); --主題日誌開始 open etl_theme_cur; --開啟主題遊標 loop select etl_seq.nextval into seq_theme from dual; --給主題序列賦值 fetch etl_theme_cur into rowresult; --將遊標中的值賦給rowresult exit when etl_theme_cur%notfound;--判斷:遊標不存在時跳出迴圈 IF rowres.site_code = rowresult.station_code THEN --判斷主題資料 delete from etl_non_oil_sales where id=seq_theme; insert into etl_non_oil_sales values(seq_theme,rowresult.station_code,rowresult.station_name,rowresult.deptid,rowresult.deptname, rowresult.itemname,rowresult.itemid,rowresult.sales_amount,rowresult.qty,rowresult.day_batch_date,rowresult.day_batch_id, rowresult.companyid,rowresult.company); update etl_theme_log set end_time=sysdate where id=seq_theme_log; end if; end loop; close etl_theme_cur; end loop; close etl_org_cur; update etl_proc_log set end_time=sysdate where id=seq_log; end ETL_NON_OIL_SALES_PROC;