then - raise_application_error oracle
Oracle PL/SQL: aumenta la excepción definida por el usuario con SQLERRM personalizado (5)
Normalmente pierdo la pista de todos mis códigos de error de tipo -20001
, así que intento 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!!
¿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!");
}
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.
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.
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;
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;