我们可以使用 RAISE 来触发异常。我们需要使用哪些特殊情况 RAISE_APPLICATION_ERROR ?
感谢。
答案 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异常代码中。