PL/SQL provides the raise_application_error built-in to do just that. When you call raise_application_error, you specify the error number and message. Here is an example of calling this built-in:
BEGIN
IF l_balance < 1000
THEN
RAISE_APPLICATION_ERROR (-20100, 'Balance too low!');
END IF;
The problem with the above code is that I have hard-coded both error number and message, both things to be avoided because these literals make code maintenance more challenging. Generally, you should centralize error messages as much as possible in a repository, and you should avoid hard-coding of error numbers in the call to raise_application_error (which must be in the -20999 to -20000 range).
In this Q&A I will focus on avoiding the hard-coding of -20100. The solution is the same as that shown for ORA-24381. I will create a package to hold declarations of my applications-specific exceptions:
CREATE OR REPLACE PACKAGE my_exceptions
IS
e_balance_too_low EXCEPTION;
en_balance_too_low CONSTANT PLS_INTEGER := -20100;
PRAGMA EXCEPTION_INIT (e_balance_too_low, -20100);
/* And a function that returns message text stored in a
repository table to avoid hard-coding those as well! */
FUNCTION errmsg_for_errnum (errnum_in IN PLS_INTEGER)
RETURN VARCHAR2;
END my_exceptions;
Now, I bet that a number of my very sharp readers will ask why I violate my oft-stated best practice of avoiding repetition of code, data values, etc. Specially, why do I use the literal -20100 twice? Why not reference the en_balance_too_low value in the PRAGMA statement, as follows:
SQL> CREATE OR REPLACE PACKAGE my_exceptions
2 IS
3 e_balance_too_low EXCEPTION;
4 en_balance_too_low CONSTANT PLS_INTEGER DEFAULT -20100;
5 PRAGMA EXCEPTION_INIT (e_balance_too_low, en_balance_too_low);
6 END my_exceptions;
7 /
The answer is simple and unfortunate: Oracle doesn't yet support this, as shown in the compile error below:
Warning: Package created with compilation errors.
SQL> sho err
Errors for PACKAGE MY_EXCEPTIONS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/4 PL/SQL: Declaration ignored
5/46 PLS-00702: second argument to PRAGMA EXCEPTION_INIT must be a
numeric literal
And now I can raise my application-specific exception by referencing the pre-defined constant:
BEGIN
IF l_balance < 1000
THEN
RAISE_APPLICATION_ERROR (
my_exceptions.en_balance_too_low
, my_exceptions.errmsg_for_errnum (
my_exceptions.en_balance_too_low);
END IF;
Why not use a central package goblal for the error msg too? (It seems unlike you not to.) You don't show the point of declaring "e_balance_to_low".
SF: OK, will do!
Note that one potential downside to having a centralized exceptions package like my_exceptions is that whenever I change that package, for example to add a new exception, I will need to recompile all programs that reference that package.
To summarize: declare and use your own named exceptions to improve the readability of your code and avoid hard-coding of exception codes.
No comments:
Post a Comment