Oracle:使用RAISE_APPLICATION_ERROR的情况如何?

时间:2009-11-19 02:56:01

标签: oracle

我们可以使用 RAISE 来触发异常。我们需要使用哪些特殊情况 RAISE_APPLICATION_ERROR

感谢。

3 个答案:

答案 0 :(得分:26)

RAISE_APPLICATION_ERROR有两种用途。第一种是用我们自己的,更有意义的消息替换通用的Oracle异常消息。第二种是创建我们自己的异常条件,而Oracle不会抛出它们。

以下程序说明了两种用法。它强制执行一项业务规则,即将来不能聘用新员工。它还会覆盖两个Oracle异常。一个是DUP_VAL_ON_INDEX,它由EMP(ENAME)上的唯一键抛出。另一个是在违反EMP(MGR)EMP(EMPNO)之间的外键时抛出的用户定义的异常(因为经理必须是现有员工)。

create or replace procedure new_emp
    ( p_name in emp.ename%type
      , p_sal in emp.sal%type
      , p_job in emp.job%type
      , p_dept in emp.deptno%type
      , p_mgr in emp.mgr%type 
      , p_hired in emp.hiredate%type := sysdate )
is
    invalid_manager exception;
    PRAGMA EXCEPTION_INIT(invalid_manager, -2291);
    dummy varchar2(1);
begin
    -- check hiredate is valid
    if trunc(p_hired) > trunc(sysdate) 
    then
        raise_application_error
            (-20000
             , 'NEW_EMP::hiredate cannot be in the future'); 
    end if;

    insert into emp
        ( ename
          , sal
          , job
          , deptno
          , mgr 
          , hiredate )
    values      
        ( p_name
          , p_sal
          , p_job
          , p_dept
          , p_mgr 
          , trunc(p_hired) );
exception
    when dup_val_on_index then
        raise_application_error
            (-20001
             , 'NEW_EMP::employee called '||p_name||' already exists'
             , true); 
    when invalid_manager then
        raise_application_error
            (-20002
             , 'NEW_EMP::'||p_mgr ||' is not a valid manager'); 

end;
/

外观如何:

SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1)
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1); END;

*
ERROR at line 1:
ORA-20000: NEW_EMP::hiredate cannot be in the future
ORA-06512: at "APC.NEW_EMP", line 16
ORA-06512: at line 1

SQL>
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate)
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate); END;

*
ERROR at line 1:
ORA-20002: NEW_EMP::8888 is not a valid manager
ORA-06512: at "APC.NEW_EMP", line 42
ORA-06512: at line 1


SQL>
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate)

PL/SQL procedure successfully completed.

SQL>
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate)
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate); END;

*
ERROR at line 1:
ORA-20001: NEW_EMP::employee called DUGGAN already exists
ORA-06512: at "APC.NEW_EMP", line 37
ORA-00001: unique constraint (APC.EMP_UK) violated
ORA-06512: at line 1

注意EXCEPTIONS块中两次调用RAISE_APPLICATION_ERROR的不同输出。将可选的第三个参数设置为TRUE意味着RAISE_APPLICATION_ERROR包含堆栈中的触发异常,这对诊断非常有用。

the PL/SQL User's Guide中有更多有用的信息。

答案 1 :(得分:3)

为了详细说明Henry的答案,您还可以使用来自raise_application_error的特定错误代码,并在客户端进行相应的处理。例如:

假设您有一个这样的PL / SQL过程来检查是否存在位置记录:

   PROCEDURE chk_location_exists
   (
      p_location_id IN location.gie_location_id%TYPE
   )
   AS
      l_cnt INTEGER := 0;
   BEGIN
      SELECT COUNT(*)
        INTO l_cnt
        FROM location
       WHERE gie_location_id = p_location_id;

       IF l_cnt = 0
       THEN
          raise_application_error(
             gc_entity_not_found,
             'The associated location record could not be found.');
       END IF;
   END;

raise_application_error允许您引发特定的错误代码。在包标题中,您可以定义:     gc_entity_not_found INTEGER := -20001;

如果您需要其他类型的错误的其他错误代码,您可以使用-20002,-20003等定义其他错误代码。

然后在客户端,您可以执行类似的操作(此示例适用于C#):

/// <summary>
/// <para>Represents Oracle error number when entity is not found in database.</para>
/// </summary>
private const int OraEntityNotFoundInDB = 20001;

您可以在try / catch

中执行代码
try
{
   // call the chk_location_exists SP
}
catch (Exception e)
{
    if ((e is OracleException) && (((OracleException)e).Number == OraEntityNotFoundInDB))
    {
        // create an EntityNotFoundException with message indicating that entity was not found in
        // database; use the message of the OracleException, which will indicate the table corresponding
        // to the entity which wasn't found and also the exact line in the PL/SQL code where the application
        // error was raised
        return new EntityNotFoundException(
            "A required entity was not found in the database: " + e.Message);
    }
}

答案 2 :(得分:1)

如果您的应用程序接受Oracle提出的错误,那么您可以使用它。我们有一个应用程序,每次发生错误时,我们调用raise_application_error,应用程序将弹出一个红色框,显示我们通过此方法提供的错误消息。

使用dotnet代码时,我只使用“raise”,dotnet异常机制会自动捕获Oracle ODP传递的错误并显示在我的catch异常代码中。