Exceptions in PL/SQL : 5
Exceptions are designed to handle runtime errors in PL/SQL.
When a PL/SQL block encounters an error during execution, it raises an exception and terminates the process.
Exceptions can occur in:
Anonymous blocks (causing immediate termination)
Subprograms (functions, procedures, etc.)
Other platforms (e.g., Oracle Forms, Java)
If exceptions are not handled, they will crash the program or propagate to the calling environment.
Attributes of Exceptions
Exceptions provide two main attributes:
Error Code – A unique identifier for the error (e.g.,
ORA-01403
for "No data found").Error Message – A brief description of the issue.
Raising Exceptions
Exceptions can be raised in two ways:
Implicitly – Oracle server detects the error and raises an exception automatically.
Explicitly – Developers raise custom exceptions based on specific business rules.
Exception Handling Methods
There are three ways to handle exceptions:
Trap and Handle – Catch the exception and take corrective actions.
Propagate – Pass the exception to the calling program or environment for handling.
Handle and Propagate – Take corrective actions but also pass the error to the caller.
Types of Exceptions in PL/SQL
Predefined Oracle Server Errors
Oracle has over 10,000 error codes, but about 20 common ones are predefined with names.
Example:
ORA-01403
(No Data Found) is predefined asNO_DATA_FOUND
.
Non-predefined Oracle Server Errors
- These do not have predefined names and must be declared explicitly in the declaration section.
User-defined Errors
These are custom errors related to business logic.
Example: Raising an exception if salary exceeds $20,000.
Handling Predefined Exceptions
The exception section is placed before the END
keyword in a PL/SQL block.
Syntax:
BEGIN
-- Your PL/SQL code here
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE('No employee found with the given ID.');
WHEN too_many_rows THEN
DBMS_OUTPUT.PUT_LINE('More than one employee found with the same name.');
END;
Handling Multiple Exceptions
If a PL/SQL block can encounter multiple exceptions, each must have a separate handler.
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE('No record found.');
WHEN too_many_rows THEN
DBMS_OUTPUT.PUT_LINE('Multiple records found. Please refine the query.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An unexpected error occurred. Contact support.');
Key Points:
If an exception is caught, the remaining handlers are skipped.
WHEN OTHERS THEN
is a generic handler that catches all unhandled exceptions.Exception handlers must be unique; two handlers cannot trap the same error.
Fetching Error Code and Message
PL/SQL provides built-in functions to fetch error details:
SQLCODE
: Returns the error number.SQLERRM
: Returns the error message.
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error Code: ' || SQLCODE || ' - ' || SQLERRM);
Nested Exception Blocks
In real-world scenarios, preventing abrupt execution termination is crucial. To handle exceptions for specific operations without terminating the entire block, nested exception blocks can be used.
DECLARE v_department_name VARCHAR2(100);
BEGIN
BEGIN
SELECT department_id INTO v_department_name FROM employees WHERE first_name = 'Steven';
EXCEPTION
WHEN too_many_rows THEN
v_department_name := 'Error in department name';
END;
DBMS_OUTPUT.PUT_LINE('Department: ' || v_department_name);
END;
Handling Non-Predefined Exceptions in PL/SQL
Non-predefined exceptions are errors that do not have specific names in the Oracle Server.
Oracle has around 10,000 error codes that are not predefined.
These exceptions cannot be trapped directly by their error codes (except using
WHEN OTHERS THEN
, which is too generic).To handle them effectively, we must declare them and assign a specific error code.
Declaring a Non-Predefined Exception
- Declare an exception variable.
cannot_update_to_null EXCEPTION;
- Assign an error code to the exception using
PRAGMA EXCEPTION_INIT
.
PRAGMA EXCEPTION_INIT(cannot_update_to_null, -1407);
PRAGMA is a compiler directive that gives instructions to the compiler.
EXCEPTION_INIT
tells the compiler to associate the given error code with the exception name.
Example
declare
cannot_update_to_null exception;
pragma exception_init(cannot_update_to_null,-01407);
begin
UPDATE employees_copy set email = null where employee_id = 100;
exception
when cannot_update_to_null then
dbms_output.put_line('You cannot update with a null value!');
end;
Alternative Approach Using WHEN OTHERS THEN
- You can handle the specific error inside a generic handler using
SQLCODE
:
WHEN OTHERS THEN
IF SQLCODE = -1407 THEN
DBMS_OUTPUT.PUT_LINE('You cannot update with a null value!');
ELSE
RAISE; -- Re-raise the exception if it's not the one we expected
END IF;
Handling User-Defined Exceptions in PL/SQL
Declaring a User-Defined Exception
The syntax is similar to non-predefined exceptions, but without an error code.
Example declaration:
too_high_salary EXCEPTION;
Raising a User-Defined Exception
To explicitly raise a user-defined exception, use the
RAISE
statement.Example:
IF v_salary_check > 20000 THEN
RAISE too_high_salary;
END IF;
Handling a User-Defined Exception
- The raised exception must be handled in the
EXCEPTION
section:
EXCEPTION
WHEN too_high_salary THEN
DBMS_OUTPUT.PUT_LINE('This salary is too high. You need to decrease it.');
Complete Example:
DECLARE
too_high_salary EXCEPTION;
v_salary_check PLS_INTEGER;
BEGIN
-- Fetch salary of the employee
SELECT salary INTO v_salary_check
FROM employees
WHERE employee_id = 100;
-- Check if salary exceeds limit
IF v_salary_check > 20000 THEN
RAISE too_high_salary;
END IF;
-- If no exception, print success message
DBMS_OUTPUT.PUT_LINE('The salary is in an acceptable range.');
EXCEPTION
WHEN too_high_salary THEN
DBMS_OUTPUT.PUT_LINE('This salary is too high. You need to decrease it.');
END;
Introduction to RAISE_APPLICATION_ERROR
In PL/SQL, predefined and user-defined exceptions are handled within a block.
However, user-defined exceptions do not have error codes and cannot be raised beyond their block.
When working with external applications (Oracle Forms, Java, etc.), we need a way to pass business exceptions to the caller.
Solution: Use
RAISE_APPLICATION_ERROR
to send custom error messages and codes to the calling application.
Syntax of RAISE_APPLICATION_ERROR
RAISE_APPLICATION_ERROR(error_code, error_message [, keep_error_stack]);
error_code: Must be between -20000 and -20999 (to avoid conflict with Oracle’s reserved codes).
error_message: Custom error message (up to 2 KB in length).
keep_error_stack (optional):
TRUE
: Keeps previous errors in the stack.FALSE
(default): Clears previous errors from the stack.
Example: Raising an Application Error
DECLARE
v_salary_check PLS_INTEGER;
BEGIN
-- Fetch employee salary
SELECT salary INTO v_salary_check FROM employees WHERE employee_id = 100;
-- Business rule: Salary should not exceed 20,000
IF v_salary_check > 20000 THEN
RAISE_APPLICATION_ERROR(-20243, 'The salary of the selected employee is too high.');
END IF;
DBMS_OUTPUT.PUT_LINE('Salary is within the acceptable range.');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
-- OUTPUT
-- ORA-20243: The salary of the selected employee is too high.
Using RAISE_APPLICATION_ERROR in the Exception Block
DECLARE
too_high_salary EXCEPTION;
BEGIN
-- Fetch salary
SELECT salary INTO v_salary_check FROM employees WHERE employee_id = 100;
-- Condition to raise exception
IF v_salary_check > 20000 THEN
RAISE too_high_salary;
END IF;
EXCEPTION
WHEN too_high_salary THEN
DBMS_OUTPUT.PUT_LINE('Handling salary error internally.');
RAISE_APPLICATION_ERROR(-20243, 'Salary exceeds limit.');
END;
-- OUTPUT
-- Handling salary error internally.
-- ORA-20243: Salary exceeds limit.