How to Name Oracle Errors with PRAGMA EXCEPTION_INIT

Handle any Oracle error by name with PRAGMA EXCEPTION_INIT, and give your own RAISE_APPLICATION_ERROR errors names that callers can catch.

Only a few dozen Oracle errors have predefined names such as NO_DATA_FOUND. To handle any other error by name, such as ORA-02292 for a parent row that still has children, or your own application errors, declare an exception and bind it to the error number with PRAGMA EXCEPTION_INIT.

Code for This Guide

The main examples are in the examples/exceptions folder of the Oracle Database 26ai code repository on GitHub, each with its output. They use NIMBUS, the sample schema of a fictional airline, which you can install with the scripts in the setup/nimbus folder.

They come from Oracle Database 26ai SQL and PL/SQL Book.

Syntax

name exception;
pragma exception_init(name, -error_number);

raise_application_error(-20000 .. -20999, 'message' [, keep_errors]);

The pragma follows the exception's declaration, in the same declaration section, and the number is negative, as SQLCODE returns it.

Handle ORA-02292 by Name

Example:

declare
  e_child_rows exception;
  pragma exception_init(e_child_rows, -2292);
begin
  delete from routes where route_id = 1;
exception
  when e_child_rows then
    dbms_output.put_line('Route 1 still has flights: ' || sqlerrm);
end;
/

Output:

Route 1 still has flights: ORA-02292: integrity constraint (NIMBUS.FLIGHTS_ROUTE_FK) violated - child record found

PL/SQL procedure successfully completed.

Deleting route 1 fails because flights reference it. The handler for e_child_rows reads more clearly than WHEN OTHERS with a test on SQLCODE.

Raise Application Errors

RAISE_APPLICATION_ERROR raises an error numbered from -20000 to -20999 with your own message, which reaches the caller like any Oracle error.

Example:

declare
  v_status flights.status%type;
begin
  select status into v_status from flights where flight_id = 30;
  if v_status <> 'SCHEDULED' then
    raise_application_error(-20001, 'Flight 30 can''t be rebooked: it is ' || v_status);
  end if;
end;
/

Output:

declare
*
ERROR at line 1:
ORA-20001: Flight 30 can't be rebooked: it is ARRIVED
ORA-06512: at line 6

Name Your Own Application Errors

Combining the two lets callers handle your application errors by name.

Example:

-- name an application error so callers can handle it by name
declare
  e_not_rebookable exception;
  pragma exception_init(e_not_rebookable, -20001);

  procedure rebook (p_flight_id number) is
    v_status flights.status%type;
  begin
    select status into v_status from flights where flight_id = p_flight_id;
    if v_status <> 'SCHEDULED' then
      raise_application_error(-20001, 'Flight ' || p_flight_id || ' is ' || v_status);
    end if;
  end;
begin
  rebook(30);
exception
  when e_not_rebookable then
    dbms_output.put_line('Handled by name: ' || sqlerrm);
end;
/

Output:

Handled by name: ORA-20001: Flight 30 is ARRIVED

PL/SQL procedure successfully completed.

The procedure raises -20001 for a flight that cannot be rebooked, and the caller catches it as e_not_rebookable. Declare such exceptions in a package specification so every caller shares the names.

Things to Know

  • Keep a list of your application error numbers and their meanings, ideally as named exceptions in one package.
  • A third argument TRUE to RAISE_APPLICATION_ERROR keeps the previous errors on the error stack.
  • Do not bind names to NO_DATA_FOUND's number; use the predefined name.

Related Guides

Conclusion

PRAGMA EXCEPTION_INIT gives a name to any Oracle error number, so handlers can catch it by name. Combine it with RAISE_APPLICATION_ERROR to define named application errors that callers can handle as clearly as built-in ones.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted