2015-12-02 35 views
0

我想創建一個數據庫過程來截斷一個表,但是如果那個截斷失敗,暫時等待並重新運行截斷。我無法鎖定表格或複製表格,然後刪除舊錶格,所以這種更困難的方法是我唯一的選擇。循環過程來截斷一個表SQL Developer

我得到一個PLS-00382錯誤我下面的代碼並難倒問題:

CREATE OR REPLACE PROCEDURE TRUNCATE_ROUTING_CACHE AS 
runcount NUMBER := 0; 
status  varchar2(10); 


BEGIN 

EXECUTE IMMEDIATE 'truncate table routing_cache'; 


IF VALUE_ERROR THEN 
status := 'FAIL'; 

    WHILE status = 'FAIL' AND runcount < 3 
     LOOP 
     sys.dbms_lock.sleep(120); 
     EXECUTE IMMEDIATE 'truncate table routing_cache'; 
      IF VALUE_ERROR THEN 
      runcount := runcount + 1; 

      ELSIF status = 'FAIL' THEN 
      status := 'SUCCESS'; 

      END IF; 

     END LOOP; 

ELSIF runcount = 0 THEN 
    status := 'SUCCESS'; 
    runcount := runcount + 1; 
END IF; 

END; 

回答

1

你不抓住這樣,你必須使用EXCEPTION WHEN結構異常。我建議您閱讀Oracle's documentation on exception handling。我也很驚訝你正在尋找一個VALUE_ERROR,這隻包括在轉換或放入變量時截斷數字/日期。它不包括表格。

這裏的所有要求都是有關的;這聽起來不像你的數據模型是正確的;也許像global temporary table會更合適?

但是,如果你真的需要做到這一點,那麼我如下簡化它:

begin 
    loop 
     begin 
     execute immediate truncate table routing_cache'; 
     exit; 
     exception when others then 
     dbms_lock.sleep(120); 
     end; 
    end loop; 
end; 

這個無限循環。如果在截斷過程中沒有發生異常,它將退出循環,否則它將休眠120s。

+0

太棒了,我篡改了一下,只跑了3次。我計劃添加額外的代碼來報告它運行的次數等。 –

0
In my opinion we should check for locks first. If lock is there then wait event should be invoked. I have pasted a snippet below which will help you to go in right direction. Let me know if this helps. 

CREATE OR REPLACE PROCEDURE TRUNCATE_ROUTING_CACHE 
AS 
    runcount NUMBER := 0; 
    status VARCHAR2(10); 
    lv_cnt PLS_INTEGER; 
BEGIN 
    --Checking first if any lock there on the object 
    SELECT COUNT(1) 
    INTO lv_cnt 
    FROM V$LOCKED_OBJECT lc, 
    ALL_OBJECTS obj 
    WHERE lc.object_id = obj.object_id 
    AND obj.OBJECT_TYPE = 'TABLE' 
    AND obj.OBJECT_NAME = 'ROUTING_CACHE'; 
    -- If lock present let it wait for 120 secs 
    WHILE lv_cnt <> 0 
    LOOP 
    sys.dbms_lock.sleep(120); 
    -- Again check foer the lock objects for any locks to continue loop 
    SELECT COUNT(1) 
    INTO lv_cnt 
    FROM V$LOCKED_OBJECT lc, 
     ALL_OBJECTS obj 
    WHERE lc.object_id = obj.object_id 
    AND obj.OBJECT_TYPE = 'TABLE' 
    AND obj.OBJECT_NAME = 'ROUTING_CACHE'; 
    END LOOP; 
    -- Once lock clears up the Truncate command will be fired 
    EXECUTE IMMEDIATE 'TRUNCATE TABLE ROUTING_CACHE'; 
END;