簡體   English   中英

添加異常處理並改進以下Oracle中的存儲過程和作業

[英]Adding exception handling and improving the below stored procedure and job in oracle

我已經在oracle數據庫中編寫了數據庫調度程序作業,該數據庫當前配置為每12小時運行一次。 該作業調用存儲過程,該存儲過程僅在mv刷新完成並且mv的上次刷新時間大於清理作業的上次運行時間時才執行增量表清理任務。

BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'TABLE_CLEAN_UP_JOB',
    job_type        => 'STORED_PROCEDURE',
    job_action      => 'TABLE_CLEAN_UP',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'freq=hourly;interval=12',
    enabled         => TRUE);
END;
/

下面是存儲過程

create or replace procedure TABLE_CLEAN_UP
is
refresh_date timestamp(6);
v_exists NUMBER;
outcome VARCHAR2(100);
cnt NUMBER;
i NUMBER := 0;
begin

SELECT count(1) into cnt FROM all_mviews WHERE owner = 'M_TO' AND mview_name = 'DC_CASHFLOW_VIEW' or  mview_name = 'DC_CASHFLOW_VIEW_ZERO' and LAST_REFRESH_TYPE='COMPLETE';

   if cnt=2 then
     FOR rec IN (SELECT * FROM all_mviews WHERE owner = 'P_SM_TO' AND mview_name = 'DC_CASHFLOW_VIEW' or  mview_name = 'DC_CASHFLOW_VIEW_ZERO' and LAST_REFRESH_TYPE='COMPLETE')
     LOOP
            Select LAST_START_DATE into refresh_date from USER_SCHEDULER_JOBS 

where JOB_NAME='TABLE_CLEAN_UP_JOB';
          if (CAST(rec.LAST_REFRESH_DATE AS TIMESTAMP) > refresh_date) then
                  i := i + 1;  
      end if; 
     END LOOP;

     if i=2 then
            delete DC_CASHFLOW_DELTA;
     end if; 
   end if;

end;
/

現在對此有兩個擔憂

首先,我沒有進行適當的異常處理,因此請在上述存儲過程中建議如何進行適當的異常處理

還請告知如何將邏輯合並到循環中。如果未進行清理,則應休眠15分鍾,然后重新嘗試。

請告知人們如何進行改進,任何建議將不勝感激

民間可以有人建議嗎

這是一個清理后的版本(當然是未經試用的)。 我退出循環,因為它似乎可以歸結為兩個數字,並且我將您的where子句中的or構造更改為in ()因為它更簡單,並且您缺少一些方括號,因此它會給出錯誤的結果。

我從不熱衷於對模式名稱進行硬編碼-也許應該將它們作為參數傳遞或從配置表中獲取?

異常處理看起來很好。 (如果沒有'TABLE_CLEAN_UP_JOB' ,它將失敗並顯示no_data_found ,但是我會說在這種情況下它應該失敗,因為缺少系統的一部分。也許特定情況下的異常處理程序可以使用raise_application_error提供更好的消息,或只是記錄一條消息並繼續,如果那是您想要的,則由您決定。)

create or replace procedure table_clean_up
is
    v_refresh_date   date;
    v_table_count_m  integer;
    v_table_count_p  integer;

begin
    select count(*) into v_table_count_m
    from   all_mviews
    where  owner = 'M_TO'
    and    mview_name in ('DC_CASHFLOW_VIEW','DC_CASHFLOW_VIEW_ZERO')
    and    last_refresh_type = 'COMPLETE';

    if v_table_count_m = 2 then
        select cast(last_start_date as date) into v_refresh_date
        from   user_scheduler_jobs
        where  job_name = 'TABLE_CLEAN_UP_JOB';

        select count(*) into v_table_count_p
        from   all_mviews m
        where  m.owner = 'P_SM_TO'
        and    m.mview_name in ('DC_CASHFLOW_VIEW', 'DC_CASHFLOW_VIEW_ZERO')
        and    m.last_refresh_type = 'COMPLETE'
        and    m.last_refresh_date > v_refresh_date;

        if v_table_count_p = 2 then
            delete dc_cashflow_delta;
        end if;
    end if;

end;

我不太了解日程安排問題。 您有一個作業'TABLE_CLEAN_UP_JOB' ,每12小時調用一次上述過程,在該過程中,您檢查自上次運行作業(12小時前)以來是否進行了MV刷新,但是如果沒有,那么您想重新計划15分鍾后重試。 我可能會丟失一些東西,但是為什么不首先安排它每15分鍾運行一次呢?

無論如何,如果您真的想要一個過程調用坐在那里重試長達12個小時,則可以按照以下方式嘗試一些操作:

create or replace procedure table_clean_up
is
    v_refresh_date   date;
    v_table_count_m  integer;
    v_table_count_p  integer;
    v_loopcount      integer := 48;
begin
    while v_loopcount > 0 loop
        select count(*) into v_table_count_m
        from   all_mviews
        where  owner = 'M_TO'
        and    mview_name in ('DC_CASHFLOW_VIEW','DC_CASHFLOW_VIEW_ZERO')
        and    last_refresh_type = 'COMPLETE';

        if v_table_count_m = 2 then
            select cast(last_start_date as date) into v_refresh_date
            from   user_scheduler_jobs
            where  job_name = 'TABLE_CLEAN_UP_JOB';

            select count(*) into v_table_count_p
            from   all_mviews m
            where  m.owner = 'P_SM_TO'
            and    m.mview_name in ('DC_CASHFLOW_VIEW', 'DC_CASHFLOW_VIEW_ZERO')
            and    m.last_refresh_type = 'COMPLETE'
            and    m.last_refresh_date > v_refresh_date;

            if v_table_count_p = 2 then
                delete dc_cashflow_delta;
                exit;
            end if;
        end if;

        dbms_lock.sleep(60 * 15);
        v_loopcount := v_loopcount -1;
    end loop;
end;

(有關休眠時間和嘗試迭代次數的幻數應該作為參數傳遞或在表中進行配置。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM