All Products
Search
Document Center

PolarDB:Error handling

Last Updated:Jul 24, 2025

PolarDB for PostgreSQL (Compatible with Oracle) supports the native PostgreSQL error handling system and is also compatible with common error handling mechanisms in Oracle syntax.

The main error handling mechanisms include the following types:

  • Predefined exceptions: Supports all predefined exceptions in native PostgreSQL and is compatible with common predefined exceptions in Oracle syntax.

  • Non-predefined exceptions: Compatible with exception variables in Oracle syntax and supports setting error codes for exception variables through EXCEPTION_INIT.

  • Custom Exception (RAISE_APPLICATION_ERROR): Compatible with the RAISE_APPLICATION_ERROR function in Oracle syntax, used to raise custom error codes and error messages.

  • Error codes and error messages: Supports both native PostgreSQL SQLSTATE error codes and is compatible with common SQLCODE error codes in Oracle syntax. It also supports SQLERRM for viewing detailed error messages.

Predefined exceptions

You can use predefined exceptions from both PostgreSQL, such as division_by_zero, and Oracle, such as zero_divide. You can raise and catch these exceptions in your SQL blocks.

Raise an exception

You can raise an exception in two ways: implicitly by executing a PL/SQL statement that causes an error or explicitly by using the RAISE statement.

The following examples show how to raise an exception:

Implicitly raise by executing PL/SQL statements

DECLARE
    result INT;
BEGIN
    result := 1 / 0;
END;

Explicitly raise with the RAISE statement

-- PostgreSQL style
BEGIN
    RAISE division_by_zero;
END;

-- Oracle style
BEGIN
    RAISE zero_divide;
END;

Catch an exception

You can catch exceptions using an EXCEPTION block. Use a WHEN clause to catch a specific exception by name or use WHEN OTHERS to catch all exceptions.

Catch a specific exception by name

-- PostgreSQL style
DECLARE
    result INT;
BEGIN
    result := 1 / 0;
EXCEPTION
    WHEN division_by_zero THEN
        DBMS_OUTPUT.PUT_LINE('division by zero');
END;

-- Oracle style
DECLARE
    result INT;
BEGIN
    result := 1 / 0;
EXCEPTION
    WHEN zero_divide THEN
        DBMS_OUTPUT.PUT_LINE('zero divide');
END;

Catch all exceptions with WHEN OTHERS

DECLARE
    result INT;
BEGIN
    result := 1 / 0;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('division by zero');
END;

Non-predefined exceptions

Oracle syntax includes many error codes that are not named, predefined exceptions. To handle these errors by name, you can declare an exception variable and associate it with an Oracle error code.

The process involves three steps:

  1. In the DECLARE section, declare an exception, such as my_exception EXCEPTION;.

  2. Use the PRAGMA EXCEPTION_INIT statement to bind the variable to a specific SQLCODE, such as PRAGMA EXCEPTION_INIT(my_exception, -1476);.

    Important

    The associated error code must be 100 (for the no_data_found exception) or a negative integer between -1000000 and -1. Only the range from -65535 to -1 maps to valid Oracle SQLCODEs.

  3. In the EXCEPTION section, use WHEN my_exception or WHEN OTHERS to catch the exception.

Example

DECLARE
    result INT;
    my_exception EXCEPTION;
    PRAGMA EXCEPTION_INIT(my_exception, -66666);
BEGIN
    result := 1 / 0;
EXCEPTION
    WHEN my_exception THEN
        DBMS_OUTPUT.PUT_LINE('zero divide');
END;

Custom Exception (RAISE_APPLICATION_ERROR)

Oracle reserves the integer range from -20999 to -20000 for predefined exceptions and non-predefined exceptions. You can use the RAISE_APPLICATION_ERROR procedure to raise a custom exception with a specific error code and message from within this range.

Example

DECLARE
    salary NUMBER := 4000;
BEGIN
    -- Validate business rules, trigger an error when conditions are not met
    IF salary < 5000 THEN
        RAISE_APPLICATION_ERROR(-20001, 'Salary is below the allowed minimum.');
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('Custom Error: ' || SQLERRM);
END;

Error codes and error messages

Within an EXCEPTION block, you can use the following built-in functions to get information about an error:

  • SQLSTATE: The native PostgreSQL error code. This is a five-character string where the first two characters represent the error class.

  • SQLCODE: The Oracle-compatible integer error code. It falls into one of three categories:

    • 100: Indicates the no_data_found exception, indicating that a query statement returned no results.

    • -65535 to -1: Indicates a standard Oracle error.

    • -99999: Indicates an invalid value or unsupported scenario in PolarDB for PostgreSQL (Compatible with Oracle).

  • SQLERRM: The error message that provides a detailed description of the exception.

Example

DECLARE
    result INT;
BEGIN
    result := 1 / 0;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('SQLSTATE: ' || SQLSTATE);
        DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
END;

The output is:

SQLCODE: -1476
SQLSTATE: 22012
SQLERRM: division by zero

Error code mapping

The following table lists supported error scenarios and maps the Oracle-style SQLCODE to its corresponding PostgreSQL-style SQLSTATE:

SQLCODE

Oracle exception name

SQLSTATE

PostgreSQL exception name

Error description

100

NO_DATA_FOUND

P0002

no_data_found

Query statement returns no results

-1

DUP_VAL_ON_INDEX

23505

unique_violation

Violation of unique constraint when inserting duplicate keys

-54

None

55P03

lock_not_available

Lock acquisition failed

-939

None

54023

too_many_arguments

Too many function arguments

-957

None

42701

duplicate_column

Duplicate column name

-960

None

42702

ambiguous_column

Ambiguous column name

-1001

INVALID_CURSOR

34000

invalid_cursor_name

Cursor is undefined or cursor name is invalid

-1031

None

42501

insufficient_privilege

Insufficient permissions

-1422

TOO_MANY_ROWS

P0003

too_many_rows

Query statement returns too many rows

-1428

None

2201E

invalid_argument_for_logarithm

Invalid log function parameter

-1428

None

2201F

invalid_argument_for_power_function

Invalid power function parameter

-1476

ZERO_DIVIDE

22012

division_by_zero

Division by zero

-1578

None

XX001

data_corrupted

Data corruption

-1821

None

22007

invalid_datetime_format

Date format error

-3125

None

08P01

protocol_violation

Communication protocol error

-4020

None

40P01

deadlock_detected

Deadlock detected

-6035

None

53000

insufficient_resources

Insufficient resources

-6113

None

53300

too_many_connections

Too many connections

-6503

None

2F005

function_executed_no_return_statement

Function has no RETURN statement

-6511

CURSOR_ALREADY_OPEN

42P03

duplicate_cursor

Cursor is defined or opened multiple times

-6531

COLLECTION_IS_NULL

2203G

collection_is_null

Collection is empty

-6532

SUBSCRIPT_OUTSIDE_LIMIT

2202E

array_subscript_error

Array index out of bounds

-6533

SUBSCRIPT_BEYOND_COUNT

2203H

subscript_beyond_count

Array index out of bounds

-6592

CASE_NOT_FOUND

20000

case_not_found

CASE statement has no matching WHEN clause

-24381

None

P0005

forall_dml_error

FOR ALL statement error

-27102

None

53200

out_of_memory

Insufficient memory

-30110

None

42601

syntax_error

Syntax error

-30156

None

53100

disk_full

Disk full

-1722

INVALID_NUMBER

-

-

Invalid TO_NUMBER function parameter

-1723

None

-

-

Column length is 0

-1724

None

-

-

Invalid FLOAT type precision

-1727

None

-

-

Invalid NUMBER type precision

-6502

VALUE_ERROR

-

-

Invalid numeric format or exceeds upper limit

-6508

None

-

-

Package function undefined

-99999

None

-

-

Current scenario not supported