Skip to Main Content

SQL & PL/SQL

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!

WITH clause within LATERAL or CROSS APPLY?

mathguyMay 24 2018 — edited May 24 2018

My original goal (coming from a problem about splitting character-separated strings) was to use a recursive subquery in a LATERAL clause. This led me to the following finding.

It seems the WITH clause does not work in LATERAL and in CROSS APPLY. This has nothing to do with recursive WITH; no WITH clause of any kind seems to work in LATERAL/CROSS APPLY.

Is this a known restriction? I checked the documentation and I didn't see it.

Or does it actually work, and I am simply not using the correct syntax?

The documented restrictions are here:

https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#SQLRF01702

- search for "lateral" on this page to find the LATERAL section, then read the    Restrictions on LATERAL   subsection. No mention that WITH clause is not permitted.

For some background and a testable case:

Note that the documentation says (in the same place):

LATERAL Specify LATERAL to designate subquery as a lateral inline view. Within a lateral inline view, you can specify tables that appear to the left of the lateral inline view in the FROM clause of a query. You can specify this left correlation anywhere within subquery (such as the SELECT, FROM, and WHERE clauses) and at any nesting level.

Notice the last five words in particular, highlighted. Indeed, experimentation shows that that works in a sub-subquery; it just doesn't work with a WITH clause. The error thrown (see below) refers specifically to the column name not being visible to the WITH clause. But the issue is not the nesting level (as we may be familiar with, from Oracle 10.2 or 11.2) - it is specifically the WITH clause.

For testing - suppose we want to select EMPNO and a flag (Y/N) for employees in the EMP table, based on whether they do or do not receive a commission. Of course this can be done in trivial ways, but I use it to illustrate LATERAL and subqueries within LATERAL.

A plain LATERAL clause works (first query). A sub-subquery within the LATERAL clause works also (second query). However, a WITH clause in LATERAL throws an error - columns from the left table are not visible to the WITH clause.

I also tried the same with CROSS APPLY instead of LATERAL; I got exactly the same results.

SQL> select e.empno, l.comm_flag

  2  from   scott.emp e,

  3         lateral ( select case when e.comm is null then 'N' else 'Y' end as comm_flag

  4                   from   dual

  5                 ) l

  6  where  rownum = 1

  7  ;

                                    EMPNO C

----------------------------------------- -

                                     7369 N

SQL> select e.empno, l.comm_flag

  2  from   scott.emp e,

  3         lateral ( select helper.comm_flag

  4                   from (                                         -- SUB-SUBQUERY. It does work!

  5                          select case when e.comm is null then 'N' else 'Y' end as comm_flag

  6                          from   dual

  7                        ) helper

  8                 ) l

  9  where  rownum = 1

10  ;

                                    EMPNO C

----------------------------------------- -

                                     7369 N

SQL> select e.empno, l.comm_flag

  2  from   scott.emp e,

  3         lateral ( with helper as ( select case when e.comm is null then 'N' else 'Y' end as comm_flag

4                                    from   dual

  5                                  )

  6                   select comm_flag from helper

  7                 ) l

  8  ;

       lateral ( with helper as ( select case when e.comm is null then 'N' else 'Y' end as comm_flag

                                                  *

ERROR at line 3:

ORA-00904: "E"."COMM": invalid identifier

Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jun 21 2018
Added on May 24 2018
10 comments
1,179 views