Oracle PL / SQL – 使用自定义SQLERRM引发用户定义的exception

是否可以创build用户定义的exception并能够更改SQLERRM?

例如:

DECLARE ex_custom EXCEPTION; BEGIN RAISE ex_custom; EXCEPTION WHEN ex_custom THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; / 

输出是“用户定义的例外”。 有没有可能改变这个讯息?

编辑:这是一些更多的细节。

我希望这个说明我想要做的更好。

 DECLARE l_table_status VARCHAR2(8); l_index_status VARCHAR2(8); l_table_name VARCHAR2(30) := 'TEST'; l_index_name VARCHAR2(30) := 'IDX_TEST'; ex_no_metadata EXCEPTION; BEGIN BEGIN SELECT STATUS INTO l_table_status FROM USER_TABLES WHERE TABLE_NAME = l_table_name; EXCEPTION WHEN NO_DATA_FOUND THEN -- raise exception here with message saying -- "Table metadata does not exist." RAISE ex_no_metadata; END; BEGIN SELECT STATUS INTO l_index_status FROM USER_INDEXES WHERE INDEX_NAME = l_index_name; EXCEPTION WHEN NO_DATA_FOUND THEN -- raise exception here with message saying -- "Index metadata does not exist." RAISE ex_no_metadata; END; EXCEPTION WHEN ex_no_metadata THEN DBMS_OUTPUT.PUT_LINE('Exception will be handled by handle_no_metadata_exception(SQLERRM) procedure here.'); DBMS_OUTPUT.PUT_LINE(SQLERRM); END; / 

实际上,有几十个这样的子块。 我想知道是否有一种方法可以为每个子块创build一个用户定义的exception,但是它会给出不同的消息,而不是为每个子块创build一个单独的用户定义的exception。

在.NET中,这就像有一个像这样的自定义exception:

  public class ColorException : Exception { public ColorException(string message) : base(message) { } } 

然后,一个方法会有这样的事情:

  if (isRed) { throw new ColorException("Red is not allowed!"); } if (isBlack) { throw new ColorException("Black is not allowed!"); } if (isBlue) { throw new ColorException("Blue is not allowed!"); } 

是。 你只需要使用RAISE_APPLICATION_ERROR函数。 如果您还想命名exception,则需要使用EXCEPTION_INIT编译指示,以便将错误编号与指定的exception相关联。 就像是

 SQL> ed Wrote file afiedt.buf 1 declare 2 ex_custom EXCEPTION; 3 PRAGMA EXCEPTION_INIT( ex_custom, -20001 ); 4 begin 5 raise_application_error( -20001, 'This is a custom error' ); 6 exception 7 when ex_custom 8 then 9 dbms_output.put_line( sqlerrm ); 10* end; SQL> / ORA-20001: This is a custom error PL/SQL procedure successfully completed. 

你可以像这样使用RAISE_APPLICATION_ERROR:

 DECLARE ex_custom EXCEPTION; BEGIN RAISE ex_custom; EXCEPTION WHEN ex_custom THEN RAISE_APPLICATION_ERROR(-20001,'My exception was raised'); END; / 

这将引发一个exception,如下所示:

 ORA-20001: My exception was raised 

错误号可以是-20001和-20999之间的任何值。

我通常会忽略所有-20001型错误代码,所以我尝试将所有的应用程序错误整合到一个很好的包中,例如:

 SET SERVEROUTPUT ON CREATE OR REPLACE PACKAGE errors AS invalid_foo_err EXCEPTION; invalid_foo_num NUMBER := -20123; invalid_foo_msg VARCHAR2(32767) := 'Invalid Foo!'; PRAGMA EXCEPTION_INIT(invalid_foo_err, -20123); -- can't use var >:O illegal_bar_err EXCEPTION; illegal_bar_num NUMBER := -20156; illegal_bar_msg VARCHAR2(32767) := 'Illegal Bar!'; PRAGMA EXCEPTION_INIT(illegal_bar_err, -20156); -- can't use var >:O PROCEDURE raise_err(p_err NUMBER, p_msg VARCHAR2 DEFAULT NULL); END; / CREATE OR REPLACE PACKAGE BODY errors AS unknown_err EXCEPTION; unknown_num NUMBER := -20001; unknown_msg VARCHAR2(32767) := 'Unknown Error Specified!'; PROCEDURE raise_err(p_err NUMBER, p_msg VARCHAR2 DEFAULT NULL) AS v_msg VARCHAR2(32767); BEGIN IF p_err = unknown_num THEN v_msg := unknown_msg; ELSIF p_err = invalid_foo_num THEN v_msg := invalid_foo_msg; ELSIF p_err = illegal_bar_num THEN v_msg := illegal_bar_msg; ELSE raise_err(unknown_num, 'USR' || p_err || ': ' || p_msg); END IF; IF p_msg IS NOT NULL THEN v_msg := v_msg || ' - '||p_msg; END IF; RAISE_APPLICATION_ERROR(p_err, v_msg); END; END; / 

然后调用errors.raise_err(errors.invalid_foo_num, 'optional extra text')来使用它,就像这样:

 BEGIN BEGIN errors.raise_err(errors.invalid_foo_num, 'Insufficient Foo-age!'); EXCEPTION WHEN errors.invalid_foo_err THEN dbms_output.put_line(SQLERRM); END; BEGIN errors.raise_err(errors.illegal_bar_num, 'Insufficient Bar-age!'); EXCEPTION WHEN errors.illegal_bar_err THEN dbms_output.put_line(SQLERRM); END; BEGIN errors.raise_err(-10000, 'This Doesn''t Exist!!'); EXCEPTION WHEN OTHERS THEN dbms_output.put_line(SQLERRM); END; END; / 

产生这个输出:

 ORA-20123: Invalid Foo! - Insufficient Foo-age! ORA-20156: Illegal Bar! - Insufficient Bar-age! ORA-20001: Unknown Error Specified! - USR-10000: This Doesn't Exist!! 
 declare z exception; begin if to_char(sysdate,'day')='sunday' then raise z; end if; exception when z then dbms_output.put_line('to day is sunday'); end; 
 create or replace PROCEDURE PROC_USER_EXP AS duplicate_exp EXCEPTION; PRAGMA EXCEPTION_INIT( duplicate_exp, -20001 ); LVCOUNT NUMBER; BEGIN SELECT COUNT(*) INTO LVCOUNT FROM JOBS WHERE JOB_TITLE='President'; IF LVCOUNT >1 THEN raise_application_error( -20001, 'Duplicate president customer excetpion' ); END IF; EXCEPTION WHEN duplicate_exp THEN DBMS_OUTPUT.PUT_LINE(sqlerrm); END PROC_USER_EXP;