Ist es möglich, benutzerdefinierte Ausnahmen zu erstellen und das SQLERRM zu ändern?
Zum Beispiel:
DECLARE
ex_custom EXCEPTION;
BEGIN
RAISE ex_custom;
EXCEPTION
WHEN ex_custom THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
Die Ausgabe lautet "Benutzerdefinierte Ausnahme". Ist es möglich, diese Nachricht zu ändern?
EDIT: Hier sind einige Details.
Ich hoffe, dieser zeigt, was ich besser machen will.
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;
/
In Wirklichkeit gibt es Dutzende dieser Unterblöcke. Ich frage mich, ob es eine Möglichkeit gibt, eine einzelne benutzerdefinierte Ausnahme für jeden dieser Unterblöcke auszulösen, aber eine andere Meldung zu geben, anstatt für jeden Unterblock eine separate benutzerdefinierte Ausnahme zu erstellen.
In .NET wäre es so, als hätte man eine benutzerdefinierte Ausnahme wie diese:
public class ColorException : Exception
{
public ColorException(string message)
: base(message)
{
}
}
Und dann hätte eine Methode ungefähr so:
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!");
}
quelle
Sie können RAISE_APPLICATION_ERROR folgendermaßen verwenden:
DECLARE ex_custom EXCEPTION; BEGIN RAISE ex_custom; EXCEPTION WHEN ex_custom THEN RAISE_APPLICATION_ERROR(-20001,'My exception was raised'); END; /
Das wird eine Ausnahme auslösen, die aussieht wie:
Die Fehlernummer kann zwischen -20001 und -20999 liegen.
quelle
Normalerweise verliere ich den Überblick über alle
-20001
Fehlercodes meines Typs, daher versuche ich, alle meine Anwendungsfehler in einem netten Paket wie dem folgenden zu konsolidieren: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; /
Rufen Sie dann
errors.raise_err(errors.invalid_foo_num, 'optional extra text')
an, um es wie folgt zu verwenden: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; /
erzeugt diese Ausgabe:
quelle
true
(anstelle der Standardeinstellungfalse
) ist, um eine vollständige Stapelverfolgung zu erhalten.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;
quelle
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;
Die Ausgabe von ORACLE 11g sieht folgendermaßen aus:
quelle