Exception Handling in Oracle PL/SQL (Examples)

⚡ Smart Summary

Exception handling in Oracle PL/SQL captures run-time errors that stop a block from executing, letting the engine transfer control to an EXCEPTION section where predefined, user-defined, and OTHERS handlers respond, raise, or propagate errors safely.

  • ⚙️ Run-time errors: An exception arises when the PL/SQL engine meets an instruction it cannot execute, such as dividing a number by zero.
  • 🧱 Block structure: Exceptions are handled in the EXCEPTION section using WHEN clauses, with WHEN OTHERS always placed last.
  • 📚 Predefined exceptions: Oracle names common errors like NO_DATA_FOUND and ZERO_DIVIDE in the STANDARD package, ready to catch directly.
  • 🛠️ User-defined exceptions: Programmers declare their own EXCEPTION variables and raise them explicitly with the RAISE keyword.
  • ⬆️ Propagation: An unhandled exception passes to the enclosing block, and RAISE re-signals it to a parent program.
  • 🤖 AI assistance: AI coding tools draft EXCEPTION blocks and flag unhandled error paths during review.

Exception Handling in Oracle PL/SQL

What is Exception Handling in PL/SQL?

An exception occurs when the PL/SQL engine encounters an instruction it cannot execute because of an error that arises at run-time. These errors are not detected at compile time and therefore must be handled only at run-time.

For example, if the PL/SQL engine receives an instruction to divide a number by zero, it raises the error as an exception. The exception is raised only at run-time by the PL/SQL engine.

An exception stops the program from executing further, so to avoid such a condition the error needs to be captured and handled separately. This process is called exception handling, in which the programmer handles the error that can occur at run-time.

Exception-Handling Syntax

Exceptions are handled at the block level. Once an exception occurs in a block, control leaves the execution part of that block, and the exception is then handled in the exception-handling part of the block. After the exception is handled, control cannot return to the execution section of that same block.

The illustration below shows how the execution section and the exception-handling section sit inside a single PL/SQL block:

Structure of a PL/SQL block with an execution and exception section

The syntax below explains how to catch and handle an exception.

BEGIN
<execution block>
.
.
EXCEPTION
WHEN <exceptionl_name>
THEN
  <Exception handling code for the “exception 1 _name’' >
WHEN OTHERS
THEN
  <Default exception handling code for all exceptions >
END;

Syntax Explanation:

  • In the syntax above, the exception-handling block contains a series of WHEN conditions to handle exceptions.
  • Each WHEN condition is followed by an exception name that is expected to be raised at run-time.
  • When an exception is raised at run-time, the PL/SQL engine searches the exception-handling part for that particular exception, starting from the first WHEN clause and moving sequentially.
  • If it finds a handler for the exception that was raised, it executes that particular handler code.
  • If no WHEN clause matches the raised exception, the PL/SQL engine executes the WHEN OTHERS part, if present. This handler is common to all exceptions.
  • After the handler runs, control leaves the current block.
  • Only one exception handler can execute for a block at run-time. After it runs, the engine skips the remaining handlers and leaves the current block.

Note: WHEN OTHERS should always be placed last in the sequence. Any handler written after WHEN OTHERS never runs, because control exits the block once WHEN OTHERS has executed.

Types of Exception

There are two types of exceptions in PL/SQL.

  • Predefined exceptions
  • User-defined exceptions

Predefined Exceptions

Oracle has predefined some common exceptions. Each predefined exception has a unique name and error number, and all of them are declared in the STANDARD package in Oracle. In code, you can use these predefined exception names directly to handle the corresponding errors. Many of them map directly to common SQL errors you meet every day.

Below are a few predefined exceptions:

Exception Error Code Exception Reason
ACCESS_INTO_NULL ORA-06530 Assigning a value to the attributes of an uninitialized object
CASE_NOT_FOUND ORA-06592 None of the WHEN clauses in a CASE statement is satisfied and no ELSE clause is specified
COLLECTION_IS_NULL ORA-06531 Using collection methods (except EXISTS) or accessing collection attributes on an uninitialized collection
CURSOR_ALREADY_OPEN ORA-06511 Trying to open a cursor that is already open
DUP_VAL_ON_INDEX ORA-00001 Storing a duplicate value in a database column that is constrained by a unique index
INVALID_CURSOR ORA-01001 Illegal cursor operations, such as closing an unopened cursor
INVALID_NUMBER ORA-01722 Conversion of a character to a number failed because of an invalid numeric character
NO_DATA_FOUND ORA-01403 A SELECT statement that contains an INTO clause fetches no rows
ROW_MISMATCH ORA-06504 The cursor variable data type is incompatible with the actual cursor return type
SUBSCRIPT_BEYOND_COUNT ORA-06533 Referring to a collection by an index number larger than the collection size
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Referring to a collection by an index number outside the legal range (for example, -1)
TOO_MANY_ROWS ORA-01422 A SELECT statement with an INTO clause returns more than one row
VALUE_ERROR ORA-06502 An arithmetic or size-constraint error (for example, assigning a value larger than the variable size)
ZERO_DIVIDE ORA-01476 Dividing a number by zero

User-defined Exception

Besides the predefined exceptions above, a programmer can create custom exceptions and handle them. They are created at the subprogram level in the declaration part and are visible only inside that subprogram. An exception defined in a package specification is a public exception and is visible wherever the package can be accessed.

Syntax: At subprogram level

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • In the syntax above, the variable ‘exception_name’ is defined as the EXCEPTION type.
  • It can then be used in the same way as a predefined exception.

Syntax: At package specification level

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • In the syntax above, the variable ‘exception_name’ is defined as the EXCEPTION type in the package specification of <package_name>.
  • It can be used across the database wherever the package ‘package_name’ can be called.

PL/SQL Raise Exception

All predefined exceptions are raised implicitly whenever the corresponding error occurs. User-defined exceptions, however, must be raised explicitly using the keyword RAISE. RAISE can be used in the ways shown below.

If RAISE is used on its own inside a handler, it propagates the already-raised exception to the parent block. It can be used only inside an exception block, as shown below.

The screenshot below shows RAISE used alone to re-raise an exception to the enclosing block:

Propagating an exception to the parent block with a bare RAISE

CREATE [ PROCEDURE | FUNCTION ]
 AS
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
             <Handler>
RAISE;
END;

Syntax Explanation:

  • In the syntax above, the keyword RAISE is used inside the exception-handling block.
  • Whenever the program encounters the exception ‘exception_name’, the exception is handled and completes normally.
  • The keyword RAISE in the handler then propagates that same exception to the parent program.

Note: When raising an exception to the parent block, the exception being raised must also be visible in the parent block; otherwise Oracle throws an error.

You can also use the keyword RAISE followed by an exception name to raise that particular user-defined or predefined exception. This form can be used in both the execution part and the exception-handling part.

The screenshot below shows RAISE followed by an exception name to raise a specific exception:

Raising a specific named exception with RAISE followed by the exception name

CREATE [ PROCEDURE | FUNCTION ]
AS
BEGIN
<Execution block>
RAISE <exception_name>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;

Syntax Explanation:

  • In the syntax above, the keyword RAISE is used in the execution part, followed by the exception ‘exception_name’.
  • This raises that particular exception at run-time, and it then needs to be handled or raised further.

Example 1: In this example, we will see:

  • How to declare an exception
  • How to raise the declared exception
  • How to propagate it to the main block

The screenshot below shows the complete block that declares sample_exception, raises it inside a nested block, and propagates it to the main block:

PL/SQL example declaring and raising a user-defined exception in a nested block

The following screenshot shows the same example continued, where the main block finally captures the propagated exception:

Output showing the exception captured first in the nested block and then in the main block

DECLARE
Sample_exception EXCEPTION;
PROCEDURE nested_block
IS
BEGIN
Dbms_output.put_line('Inside nested block');
Dbms_output.put_line('Raising sample_exception from nested block');
RAISE sample_exception;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in nested block. Raising to main block');
RAISE;
END;
BEGIN
Dbms_output.put_line('Inside main block');
Dbms_output.put_line('Calling nested block');
Nested_block;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in main block');
END;
/

Code Explanation:

  • Code line 2: Declaring the variable ‘sample_exception’ as an EXCEPTION type.
  • Code line 3: Declaring the procedure nested_block.
  • Code line 6: Printing the statement “Inside nested block”.
  • Code line 7: Printing the statement “Raising sample_exception from nested block”.
  • Code line 8: Raising the exception using ‘RAISE sample_exception’.
  • Code line 10: Exception handler for the exception sample_exception in the nested block.
  • Code line 11: Printing the statement “Exception captured in nested block. Raising to main block”.
  • Code line 12: Raising the exception to the main block (propagating it).
  • Code line 15: Printing the statement “Inside main block”.
  • Code line 16: Printing the statement “Calling nested block”.
  • Code line 17: Calling the nested_block procedure.
  • Code line 19: Exception handler for sample_exception in the main block.
  • Code line 20: Printing the statement “Exception captured in main block”.

Important points to note in Exception

  • In a function, an exception should always either return a value or raise the exception further; otherwise Oracle throws a ‘Function returned without a value’ error at run-time.
  • Transaction control statements can be issued inside the exception-handling block.
  • SQLERRM and SQLCODE are built-in functions that return the exception message and the exception code respectively.
  • If an exception is not handled, then by default all active transactions in that session are rolled back.
  • RAISE_APPLICATION_ERROR (-<error_code>, <error_message>) can be used instead of RAISE to raise an error with a custom code and message. The error code must be between -20000 and -20999.

FAQs

PRAGMA EXCEPTION_INIT associates a user-declared exception name with a specific Oracle error number. After binding, you can trap that ORA error by name in a WHEN clause instead of using WHEN OTHERS and checking SQLCODE.

SQLCODE returns the numeric error code of the current exception, while SQLERRM returns its text message. Both are called inside an exception handler, most often the WHEN OTHERS block, to log or display what went wrong.

Avoid a WHEN OTHERS that swallows every error silently. Without logging SQLCODE and SQLERRM or re-raising with RAISE, it hides bugs. Use it only to log, clean up, and then propagate the exception.

RAISE_APPLICATION_ERROR accepts an error number between -20000 and -20999 and a message up to 2048 bytes. It stops execution and returns a custom error to the calling application, making a user-defined condition look like a native Oracle error.

Not in the same block — once control moves to the EXCEPTION section, that block ends. To continue, wrap the risky statement in an inner BEGIN…EXCEPTION…END block; after it handles the error, the outer block keeps executing.

An error is any run-time or compile problem in the code. An exception is the PL/SQL run-time mechanism that represents a run-time error, transferring control to the EXCEPTION section so the program can respond instead of terminating abruptly.

Yes. AI assistants and machine-learning code reviewers draft EXCEPTION blocks, suggest which predefined exceptions to catch, and flag code paths that lack handlers. A developer should still confirm the logic and error messages before deploying.

GitHub Copilot autocompletes WHEN clauses, RAISE_APPLICATION_ERROR calls, and full EXCEPTION blocks from a short comment describing intent. It speeds routine handler coding, though generated error codes and messages need review for accuracy.

Summarize this post with: