首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Oracle PL/SQL -使用自定义SQLERRM引发用户定义的异常

Oracle PL/SQL -使用自定义SQLERRM引发用户定义的异常
EN

Stack Overflow用户
提问于 2011-05-17 00:32:56
回答 5查看 328.1K关注 0票数 81

是否可以创建用户定义的异常并能够更改SQLERRM?

例如:

代码语言:javascript
复制
DECLARE
    ex_custom       EXCEPTION;
BEGIN
    RAISE ex_custom;
EXCEPTION
    WHEN ex_custom THEN
        DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/

输出是“用户定义的异常”。是否有可能更改该消息?

编辑:这里有更多的细节。

我希望这篇文章能说明我正在努力做得更好。

代码语言:javascript
复制
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;
/

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

在.NET中,这有点像拥有一个自定义异常,如下所示:

代码语言:javascript
复制
    public class ColorException : Exception
    {
        public ColorException(string message)
            : base(message)
        {
        }
    }

然后,一个方法应该是这样的:

代码语言:javascript
复制
        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!");
        }
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-05-17 00:39:03

是。您只需使用RAISE_APPLICATION_ERROR函数。如果您还想为异常命名,则需要使用EXCEPTION_INIT杂注,以便将错误号与命名的异常相关联。就像这样

代码语言:javascript
复制
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.
票数 150
EN

Stack Overflow用户

发布于 2011-05-17 00:35:34

您可以像这样使用RAISE_APPLICATION_ERROR:

代码语言:javascript
复制
DECLARE
    ex_custom       EXCEPTION;
BEGIN
    RAISE ex_custom;
EXCEPTION
    WHEN ex_custom THEN
        RAISE_APPLICATION_ERROR(-20001,'My exception was raised');
END;
/

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

代码语言:javascript
复制
ORA-20001: My exception was raised

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

票数 40
EN

Stack Overflow用户

发布于 2013-07-18 02:51:38

我通常会忘记所有的-20001-type错误代码,所以我尝试将所有的应用程序错误合并到一个很好的包中,如下所示:

代码语言:javascript
复制
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')来使用它,如下所示:

代码语言:javascript
复制
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;
/

生成以下输出:

代码语言:javascript
复制
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!!
票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6020450

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档