Oracle PL / SQL: aumenta la excepción definida por el usuario con SQLERRM personalizado

¿Es posible crear excepciones definidas por el usuario y poder cambiar el SQLERRM?

Por ejemplo:

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

El resultado es “Excepción definida por el usuario”. ¿Es posible cambiar ese mensaje?

EDITAR: Aquí hay más detalles.

Espero que este ilustre lo que trato de hacer mejor.

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

En realidad, hay docenas de esos subbloques. Me pregunto si hay una forma de hacer que una única excepción definida por el usuario para cada uno de esos subbloques se eleve, pero que proporcione un mensaje diferente, en lugar de crear una excepción separada definida por el usuario para cada subbloque.

En .NET, sería algo así como tener una excepción personalizada como esta:

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

Y luego, un método tendría algo como esto:

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

Sí. Solo tiene que usar la función RAISE_APPLICATION_ERROR . Si también desea nombrar su excepción, deberá usar el pragma EXCEPTION_INIT para asociar el número de error a la excepción especificada. Algo como

 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. 

Puede usar RAISE_APPLICATION_ERROR así:

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

Eso levantará una excepción que se ve así:

 ORA-20001: My exception was raised 

El número de error puede ser cualquier cosa entre -20001 y -20999.

Normalmente pierdo la pista de todos mis códigos de error de tipo -20001 , así que bash consolidar todos mis errores de aplicación en un buen paquete como este:

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

Luego llame a errors.raise_err(errors.invalid_foo_num, 'optional extra text') para usarlo, como tal:

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

produce esta salida:

 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; 
Intereting Posts