2010-01-22 67 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; 

那么你会怎么改写它,所以它看起来不那么“如果”?这有点乱,我不得不承认。无论如何,至少你给了我很实际的见解。 我想看到一些更好的窍门,如果你想,我很感兴趣。