2011-11-10 55 views
0

我有以下...Oracle異常處理 - 這是否正確?

IF CONDITION1 THEN 

     -- SELECT STATEMENT MIGHT RETURN DATA 

     IF CONDITION2 THEN 

       -- SELECT COUNT 

      IF CONDITION3 THEN 



        INSERT INTO TABLE 
          (
          --- 
          ) 
        VALUES (
          --- 
          ); 


      End IF; 


    END IF; 


END IF; 


EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
RETURN; 

END of Trigger 

這是處理例外內CONDITION1 select語句的正確道路?

回答

3

PL/SQL有沒有辦法恢復到錯誤的部位,所以你需要創建一個要忽略特定的錯誤部分的周圍塊:

IF CONDITION1 THEN 
     BEGIN 
     -- SELECT STATEMENT MIGHT RETURN DATA 
     EXCEPTION 
      WHEN NO_DATA_FOUND THEN 
       NULL; 
     END; 
     IF CONDITION2 THEN 
       -- SELECT COUNT 
      IF CONDITION3 THEN 
        INSERT INTO TABLE 
          (
          --- 
          ) 
        VALUES (
          --- 
          ); 
      End IF; 
    END IF; 
END IF; 
END TRIGGER_NAME; 

另一種方法是使用一個明確的光標,它在空時不會返回錯誤:

DECLARE 
    CURSOR cur_sample is select dummy from dual where 1=0; 
    v_dummy dual.dummy%type; 
BEGIN 
    IF CONDITION1 THEN 
     open cur_sample; 
     fetch cur_sample into v_dummy; 
     close cur_sample; 
     IF CONDITION2 THEN 
       -- SELECT COUNT 
      IF CONDITION3 THEN 
        INSERT INTO TABLE 
          (
          --- 
          ) 
        VALUES (
          --- 
          ); 
      End IF; 
     END IF; 
    END IF; 
END; 
+0

加1如何在pl.sql中做一個空的錯誤處理程序 - null; –

3

取決於「正確」。你提出的是句法上有效的,是的。但是你沒有告訴我們你究竟想要發生什麼,所以我們不能告訴你你發佈的代碼是否會真正做到你想要的。

從業務邏輯的角度來看,如果SELECT INTO返回0行,你確定它確實不是錯誤嗎?如果你捕捉併吞下一個異常,這意味着你知道這不是一個真正的錯誤。但是,如果您編寫的是SELECT INTO,那意味着您只需要一行。這些陳述當然是可能的,但它確實是一個例外,並且不應該簡單地被吞噬和忽略,這會更常見。

通常,我寧願將異常處理程序儘可能地靠近儘可能拋出異常的查詢。我會覺得清潔劑有類似

IF condition1 
THEN 
    BEGIN 
    <<select statement>> 
    EXCEPTION 
    WHEN no_data_found 
    THEN 
     <<do something>> 
    END; 

    IF condition2 
    THEN 
    ... 
    END IF; 
END IF; 

這樣,如果你結束了在你的程序中的多個地方,一個NO_DATA_FOUND可能會引發異常,這將是明確哪些異常預期的,哪些是意外。

當你開始有三層嵌套的IF語句時,我傾向於懷疑你想要將代碼重構爲多個過程,以使代碼更清晰。例如,不是有一個嵌套的執行SELECT語句的PL/SQL塊,捕獲異常並處理異常,它可能會更清晰地擁有一個單獨的函數,它可以完成所有這些操作,然後從觸發器中調用該函數。

+0

再看一下OP的代碼。那'返回'肯定不會工作... – Allan

+0

@Allan - 爲什麼不呢?從異常處理程序中的PL/SQL塊返回在語法上是有效的。這可能不是正確的行爲,但它的有效語法 SQL> create table t(col1 number); 已創建表。 SQL>創建觸發器trg_t 2在插入之前t 3對於每行 4聲明 5 l_emp_rec emp%rowtype; 6 begin 7 select * 8 into l_emp_rec 9 from emp 10 where empno =:new.col1; 11例外 12當no_data_found 13然後 14返回; 15 end; 16/ 已創建觸發器。 SQL> insert into t values(1); 已創建1行。 –

+0

你說得對(當然)。我完全不知道這個命令(功能之外)。我仍然認爲這種行爲不會是OP期望的,我相信這是從錯誤現場恢復執行。 – Allan