Friday, 26 August 2011

Handling exceptions raised by Oracle

Of course, many exceptions that Oracle raises have not been given names using the exception_init pragma. For example, suppose you are working with FORALL with the SAVE EXCEPTIONS clause to insert data very quickly using collections. If one of the rows being inserted causes an error, Oracle will "save up" the error information. After it has inserted as many rows as possible, it will then raise the ORA-24381 exception.
You could write code as shown below to catch this exception

EXCEPTION
WHEN OTHERS
THEN
IF SQLCODE = -24381
THEN
... iterate through the SQL%BULK_EXCEPTIONS array
ELSE
RAISE;
END IF;
END;

I strongly recommend, however, that you do not do this. There are two big problems with such code:
1. It is hard to understand and maintain. Most programmers will not know what that number means and will find the code intimidating.
2. The original line on which the error was raised is lost. I use raise; to re-raise any exception besides ORA-24381. When and if I call dbms_utility.format_error_backtrace in an outer block, it will only trace back to this raise; statement, not the original line on which the error was originally raised.
A much better approach is to give a name to the ORA-24381 exception, either directly inside the block of code in which the error may be raised, or in a package specification. Here is an example of this approach:

CREATE OR REPLACE PACKAGE oracle_exceptions
IS
e_forall_error EXCEPTION;
PRAGMA EXCEPTION_INIT (e_forall_error, -24381);
...
END oracle_exceptions;
and now a rewrite of my exception section:
EXCEPTION
WHEN oracle_exceptions.e_forall_error
THEN
... iterate through the SQL%BULK_EXCEPTIONS array
END;

With my named exception, I can now avoid a when others clause entirely (unless needed for some other purpose). I catch only the specific exception by name, and let all others propagate unhandled to the outer block. And my code is much more self-explanatory.

No comments:

Post a Comment