Oracle PL / SQL-사용자 지정 SQLERRM을 사용하여 사용자 정의 예외 발생


79

사용자 정의 예외를 생성하고 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;
/

실제로 이러한 하위 블록이 수십 개 있습니다. 각 하위 블록에 대해 단일 사용자 정의 예외를 발생시키는 방법이 있는지 궁금하지만 각 하위 블록에 대해 별도의 사용자 정의 예외를 생성하는 대신 다른 메시지를 제공하도록합니다.

.NET에서는 다음과 같은 사용자 지정 예외가있는 것과 같습니다.

    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!");
        }

답변:


149

예. RAISE_APPLICATION_ERROR기능 을 사용하기 만하면 됩니다. 예외의 이름도 지정하려면 EXCEPTION_INITpragma 를 사용 하여 오류 번호를 명명 된 예외에 연결해야합니다. 같은 것

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.

1
정확히 내가 필요한 것! 당신이 이미 내 질문에 답한 동안 편집을 한 것 같습니다. 대단히 감사합니다.
tgxiii

39

다음과 같이 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;
/

다음과 같은 예외가 발생합니다.

ORA-20001: My exception was raised

오류 번호는 -20001에서 -20999 사이입니다.


21

일반적으로 모든 -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!!

1
좋은 팁! 내 프로젝트에 매우 유용했습니다!
SnakeSheet 2014

1
이것은 좋은 습관입니다. raise_application_error 에 대한 두 가지 사소한 문제는 1) 두 번째 매개 변수의 크기가 2048 바이트로 제한되고 2) 전체 스택 추적을 얻으려면 세 번째 매개 변수가 true(기본값 대신) 선호 false됩니다.
user272735

5
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;

2
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;

ORACLE 11g 출력은 다음과 같습니다.

Connecting to the database HR. 
ORA-20001: Duplicate president customer excetpion 
Process exited. 
Disconnecting from the database HR

ORACLE 11g 출력은 다음과 같습니다.-데이터베이스 HR에 연결. ORA-20001 : 중복 사장 고객 excetpion 프로세스가 종료되었습니다. HR 데이터베이스에서 연결을 끊습니다.
Raj Sharma 2015

이것은 EXCEPTION 블록을 제외하고는 (아이러니하게도) 좋은 것입니다. 거의 모든 상황에서 WHEN 절에서 처리 된 예외는 호출 프로그램으로 다시 발생해야합니다. 호출 프로그램은 호출 된 루틴이 실패했음을 알아야합니다. 단순히 DBMS_OUTPUT을 사용하는 것만으로는 충분하지 않습니다. 호출 프로그램이 서버 출력 버퍼를 처리 할 수 ​​없거나 호출 프로그램이 오류를 승인하도록 강제하지 않기 때문입니다.
APC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.