2010-01-22 78 views
1

我有這樣的過程:範圍引發異常,處理自己的異常在PLSQL代碼

create or replace PROCEDURE CONVERTE 
IS 
    CURSOR oldemployees IS 
     SELECT * 
     FROM emp1 
     WHERE data_saida= NULL; 

    new_ndep emp1.num_dep%type; 
    bi_inexistente EXCEPTION; 
    dep_inexistente EXCEPTION; 
    employeeNr emp1.num_empregado%type; 

BEGIN 
    FOR old_emp IN oldemployees 
    LOOP 
    employeeNr:= old_emp.num_empregado; 
     if (old_emp.bi = NULL) then 
     raise bi_inexistente; 
    else 
     IF (old_emp.num_dep>20) THEN 
       SELECT ndep_novo INTO new_ndep FROM Converte_dep WHERE ndep_antigo= old_emp.num_dep; 
     elsif (old_emp.num_dep = NULL) then 
      new_ndep:= 0; 
      raise dep_inexistente;  
     end if; 
     INSERT INTO EMP2 VALUES (old_emp.bi, old_emp.nome, old_emp.morada, old_emp.data_entrada, old_emp.data_saida, new_ndep); 
     COMMIT; 
    end if; 
    end loop; 

EXCEPTION 
when bi_inexistente then 
    INSERT INTO ERROS VALUES(employeeNr, 'BI Inexistente'); 
    COMMIT; 

when dep_inexistente then 
    INSERT INTO ERROS VALUES(employeeNr, 'Departamento Inexistente'); 
    COMMIT; 
end; 

我想要做的INSERT INTO EMP2 VALUES(old_emp.bi,old_emp.nome,old_emp.morada,old_emp。 data_entrada,old_emp.data_saida,new_ndep);即使在提高dep_inexistente後,但在閱讀oracle的參考後,我有點困惑;基本上,當它是空的,我不想做那個插入,否則我想插入,即使部門號是空的(我把它轉爲0)。

那麼,是代碼得到它的權利,或者我應該如何提高我的異常或辦理我的案件預先定義的異常?

回答

2

我不認爲應該將異常用作不雅的GOTO語句。如果你想構建你的代碼,你可以使用過程(和子過程)。如果工作是在代碼中的一個地方完成的,只需使用RETURN語句。僅在有意義時才捕捉異常。

1

。在你的代碼中的錯誤:old_emp.num_dep = NULL不能正常工作,它始終是假的。

假設它會一直old_emp.num_dep IS NULL,那麼我想根據自己的intenion您的代碼將無法正常工作。將繞過INSERT INTO EMP2提出異常。

如果這是我的代碼,邏輯是這樣的,你可以決定它是不是插入EMP2的情況下,該部門缺少一個真正的錯誤,我也不會引發異常。你沒有任何損失的信息,因爲你總是可以看到有失蹤的部門(即與0每EMP百貨)

BTW是有使用0系一個特別的原因?爲什麼不使用NULL?顯然你已經決定讓員工沒有部門是可以的,NULL是一個公平的表示。

如果你堅持認爲它實際上是對EMP錯過一個部門一個錯誤,但還是覺得它是確定反正插入EMP,我會考慮這樣寫的:

IF ... THEN 
    ... -- ok 
END IF; 
INSERT INTO EMP2 VALUES (
    old_emp.bi, old_emp.nome, old_emp.morada, old_emp.data_entrada, old_emp.data_saida, 
    NVL(new_ndep, 0) 
); 
IF new_ndep IS NULL THEN 
    raise dep_inexistente; 
END IF; 

我但是,要求你在代碼中添加一些註釋,因爲如果我能找到上面寫的代碼,我可能會懷疑有一個bug。

3

我想要做的INSERT INTO VALUES EMP2 (old_emp.bi,old_emp.nome, old_emp.morada,old_emp.data_entrada, old_emp.data_saida,new_ndep);飼養dep_inexistente

即使 後,關鍵是要提高該異常做插入之後。引發的異常實際上是GOTO語句 - 控制流直接傳遞給EXCEPTIONS塊。在接下來的重寫中,我使用了new_dep的設置作爲引發異常的信號。您可能會意識到其他一些業務邏輯會使這種方法失效(即爲什麼記錄將部門歸零)有一些合理的原因。在這種情況下,您需要設置一個標誌。關於你的一般方法

create or replace PROCEDURE CONVERTE IS 
    CURSOR oldemployees IS 
     SELECT * 
     FROM emp1 
     WHERE data_saida= NULL; 
    new_ndep emp1.num_dep%type; 
    bi_inexistente EXCEPTION; 
    dep_inexistente EXCEPTION; 
    employeeNr emp1.num_empregado%type; 
BEGIN 
    FOR old_emp IN oldemployees 
    LOOP 
     employeeNr:= old_emp.num_empregado; 
     if (old_emp.bi is NULL) then 
      raise bi_inexistente; 
     else 
      if (old_emp.num_dep>20) THEN 
       SELECT ndep_novo INTO new_ndep FROM Converte_dep WHERE ndep_antigo= old_emp.num_dep; 
      elsif (old_emp.num_dep is NULL) then 
       new_ndep:= 0; 
      end if; 
      INSERT INTO EMP2 VALUES (old_emp.bi, old_emp.nome, old_emp.morada, old_emp.data_entrada, old_emp.data_saida, new_ndep); 
      COMMIT; 
      if new_ndep = 0 then 
       raise dep_inexistente;  
      end if; 
     end if; 
    end loop; 
EXCEPTION 
    when bi_inexistente then 
     INSERT INTO ERROS VALUES(employeeNr, 'BI Inexistente'); 
     COMMIT; 
    when dep_inexistente then 
     INSERT INTO ERROS VALUES(employeeNr, 'Departamento Inexistente'); 
     COMMIT; 
end; 

三件事:

  1. 任何異常都會帶有短路循環。沒有進一步的行會被處理
  2. 因爲你是在循環中commiting它可能很難重新運行該程序,不會因爲你能夠輕鬆地從你離開的地方取貨。
  3. 在循環內部提交可能會導致ORA-1555或ORA-1002錯誤的問題,尤其是如果這是一個長時間運行的查詢。

編輯

其實你的代碼引起人們對程序邏輯提了一大堆問題。遠遠超過我想要進入這裏。上面列出的三個是一般的「最佳實踐」問題,但條件流的詳細邏輯看起來有點不合適。但是,我不知道你正在執行的業務規則。

0

所以,如果我把它的例外會是這樣:

create or replace PROCEDURE CONVERTE IS 
     CURSOR oldemployees IS 
      SELECT * 
      FROM emp1 
      WHERE data_saida= NULL; 
     new_ndep emp1.num_dep%type; 
     bi_inexistente EXCEPTION; 
     dep_inexistente EXCEPTION; 
     employeeNr emp1.num_empregado%type; 
    BEGIN 
     FOR old_emp IN oldemployees 
     LOOP 
      employeeNr:= old_emp.num_empregado; 
      if (old_emp.bi is NULL) then 
       raise bi_inexistente; 
      else 
       if (old_emp.num_dep>20) THEN 
        SELECT ndep_novo INTO new_ndep FROM Converte_dep WHERE ndep_antigo= old_emp.num_dep; 
       else 
        INSERT INTO EMP2 VALUES (old_emp.bi, old_emp.nome, old_emp.morada, old_emp.data_entrada, old_emp.data_saida,nvl(old_emp.num_dep,0)); 
       end if; 
       if new_ndep is NULL then 
        raise dep_inexistente;  
       end if; 
      end if; 
     end loop; 
    EXCEPTION 
     when bi_inexistente then 
      INSERT INTO ERROS VALUES(employeeNr, 'BI Inexistente'); 
      COMMIT; 
     when dep_inexistente then 
      INSERT INTO ERROS VALUES(employeeNr, 'Departamento Inexistente'); 
      COMMIT; 
    end; 

或者我可以做什麼被告知,沒有引發異常;但我仍然需要使用遊標。

create or replace 
    PROCEDURE CONVERTE2 IS 
     CURSOR oldemployees IS 
      SELECT * 
      FROM emp1 
      WHERE data_saida= NULL; 
     new_ndep emp1.num_dep%type; 
     bi_inexistente EXCEPTION; 
     dep_inexistente EXCEPTION; 
     employeeNr emp1.num_empregado%type; 
     v_error_code NUMBER:=0; 
     v_error_message VARCHAR2(255); 

    BEGIN 
     FOR old_emp IN oldemployees 
     LOOP 
      employeeNr:= old_emp.num_empregado; 
      if (old_emp.bi is NULL) then 
       INSERT INTO ERROS VALUES(employeeNr, 'BI Inexistente'); 
      else 
       if (old_emp.num_dep>20) THEN 
        SELECT ndep_novo INTO new_ndep FROM Converte_dep WHERE ndep_antigo= old_emp.num_dep; 
       else 
        INSERT INTO EMP2 VALUES (old_emp.bi, old_emp.nome, old_emp.morada, old_emp.data_entrada, old_emp.data_saida,nvl(old_emp.num_dep,0)); 
       end if; 
       if new_ndep is NULL then 
        INSERT INTO ERROS VALUES(employeeNr, 'Departamento Inexistente'); 
       end if; 
      end if; 
     end loop; 
     COMMIT; 

    EXCEPTION 
     When others Then 
     ROLLBACK; 
     /*eventually log something into erro table*/ 

    end; 

那麼你會怎麼改寫它,所以它看起來不那麼「如果」?這有點亂,我不得不承認。無論如何,至少你給了我很實際的見解。 我想看到一些更好的竅門,如果你想,我很感興趣。