Skip to Main Content

Oracle Database Express Edition (XE)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

ORA-22922: nonexistent LOB value in Oracle 18c when fetching CLOB values from scalar subquery

Lukas EderAug 22 2024

I'm using the latest Oracle 18c (18.4.0.0.0) version from here: https://hub.docker.com/r/gvenzl/oracle-xe/tags. The following problem no longer reproduces with 23ai. I'm not sure if it has been fixed in a non XE patch version of 18c, if so, please ignore this report. I've also documented this issue on Stack Overflow here: https://stackoverflow.com/q/78900296/521799

The following statement using Java / ojdbc doesn't work on Oracle 18c, but works fine on Oracle 23ai:

try (Statement s = connection.createStatement()) {
    try (ResultSet rs = s.executeQuery(
        """
        SELECT (SELECT to_clob('123412341234') x FROM dual)
        FROM dual
        CONNECT BY LEVEL <= 20
        """
    )) {
        while (rs.next()) {
            System.out.println(rs.getString(1));
        }
    }
}

After successfully fetching the first 10 rows, the following error is raised:

123412341234
123412341234
123412341234
123412341234
123412341234
123412341234
123412341234
123412341234
123412341234
123412341234
ORA-22922: nonexistent LOB value

It doesn't appear to be strictly ojdbc related, as I can reproduce a similar problem also in SQL*Plus:

SQL> SELECT (SELECT to_clob('123412341234') x FROM dual)
  2  FROM dual
  3  CONNECT BY LEVEL <= 11;

(SELECTTO_CLOB('123412341234')XFROMDUAL)
--------------------------------------------------------------------------------
123412341234
ERROR:
ORA-22922: nonexistent LOB value

Workarounds include:

Concatenate an empty **CLOB**

SELECT (SELECT to_clob('123412341234') x FROM dual) || to_clob('')
FROM dual
CONNECT BY LEVEL <= 20

Wrap the scalar subquery in a **to_clob()** function call

SELECT to_clob((SELECT to_clob('123412341234') x FROM dual))
FROM dual
CONNECT BY LEVEL <= 20

Increase the ojdbc fetch size

try (Statement s = connection.createStatement()) {
    s.setFetchSize(1000);
    try (ResultSet rs = s.executeQuery(
        """
        SELECT (SELECT to_clob('123412341234') x FROM dual)
        FROM dual
        CONNECT BY LEVEL <= 20
        """
    )) {
        while (rs.next()) {
            System.out.println(rs.getString(1));
        }
    }
}

Fetch JDBC **Clob** values, and delay **Clob.free()** calls

try (Statement s = connection.createStatement()) {
    try (ResultSet rs = s.executeQuery(
        """
        SELECT (SELECT to_clob('123412341234') x FROM dual)
        FROM dual
        CONNECT BY LEVEL <= 20
        """
    )) {
        List<Clob> clobs = new ArrayList<>();

        while (rs.next()) {
            Clob clob = rs.getClob(1);
            clobs.add(clob);
            System.out.println(clob.getSubString(1, (int) clob.length()));
        }

        for (Clob clob : clobs)
            clob.free();
    }
}

Delay the **Clob** freeing by the fetch size

try (Statement s = connection.createStatement()) {
    try (ResultSet rs = s.executeQuery(
        """
        SELECT (SELECT to_clob('123412341234') x FROM dual)
        FROM dual
        CONNECT BY LEVEL <= 100
        """
    )) {
        Deque<Clob> clobs = new ArrayDeque<>();

        while (rs.next()) {
            Clob clob = rs.getClob(1);
            clobs.add(clob);
            System.out.println(clob.getSubString(1, (int) clob.length()));

            int size = clobs.size() - s.getFetchSize();
            while (size --> 0)
                clobs.pollFirst().free();
        }

        for (Clob clob : clobs)
            clob.free();
    }
}

The last example really hints at the underlying problem, where it seems that scalar subquery caching and fetch size (row prefetch) caching don't play nicely with each other.

This post has been answered by Loïc Lefèvre-Oracle on Aug 22 2024
Jump to Answer
Comments
Post Details
Added on Aug 22 2024
5 comments
246 views