Subquery Factoring in Oracle 11g

2

For the last two days the AMIS 7Up Workshop took place in our office in Nieuwegein. The training consists of two SQL and another two days of PL/SQL. During the first two days a lot of SQL subjects are reviewed.

One of them is Subquery Factoring, better known as the “WITH clause”. Subquery Factoring lets you assign a name to a subquery block. Let me show you a small example:

SQL> with ordered_emps as
  2  (select ename
  3        , job
  4        , sal
  5        , deptno
  6     from emp
  7    order by ename
  8  )
  9  select *
 10    from ordered_emps
 11  ;
<span id="more-4252"></span>
ENAME      JOB              SAL     DEPTNO
---------- --------- ---------- ----------
ADAMS      CLERK           1100         20
ALLEN      SALESMAN        1600         30
BLAKE      MANAGER         2850         30
CLARK      MANAGER         2450         10
FORD       ANALYST         3000         20
JAMES      CLERK            950         30
JONES      MANAGER         2975         20
KING       PRESIDENT       5000         10
MARTIN     SALESMAN        1250         30
MILLER     CLERK           1300         10
SCOTT      ANALYST         3000         20
SMITH      CLERK            800         20
TURNER     SALESMAN        1500         30
WARD       SALESMAN        1250         30

14 rows selected.

I know this is a contrived example, but it shows you what Subquery Factoring can do. What really adds p’zazz to this feature is the possibility to add multiple named subquery blocks, even using the subquery previously defined, like this:

SQL&gt; with ordered_emps as
  2  (select ename
  3        , job
  4        , sal
  5        , deptno
  6     from emp
  7    order by ename
  8  )
  9  , top3 as
 10  (select *
 11     from ordered_emps
 12    where rownum &lt;= 3
 13  )
 14  select *
 15    from top3
 16  ;

ENAME      JOB              SAL     DEPTNO
---------- --------- ---------- ----------
ADAMS      CLERK           1100         20
ALLEN      SALESMAN        1600         30
BLAKE      MANAGER         2850         30

In the example above, you can see that the named query “top3″ uses the previously named query “ordered_emps”. It’s almost like adding procedural logic to a SQL statement.

Things keep changing,… for the better

The catch, at least prior to Oracle 11g, was that the named query must be used in the SQL statement. Wether in another named query (like above) or in the main SELECT statement (like the first example).

If you would declare a named query and not use it, you would get an exception:

SQL&gt; with ordered_emps as
  2  (select ename
  3        , job
  4        , sal
  5        , deptno
  6     from emp
  7    order by ename
  8  )
  9  , top3 as
 10  (select *
 11     from ordered_emps
 12    where rownum &lt;= 3
 13  )
 14  select *
 15    from ordered_emps
 16  /

  from ordered_emps
       *
ERROR at line 15:
ORA-32035: unreferenced query name defined in WITH clause

We did specify “Top3″ as a named query but never use it in the SQL statement. And this is what I have been telling during the 7Up training all along.

Needless to say something changed in Oracle 11g. This requirement is no longer present.  I couldn’t find it in the documentation though. Probably because I’m looking in the wrong place…

 

SQL&gt; select *
  2    from v$version
  3  /


BANNER
------------------------------------------------------------
Personal Oracle Database 11g Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE    11.1.0.6.0      Production
TNS for 32-bit Windows: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SQL&gt; with ordered_emps as
  2  (select ename
  3        , job
  4        , sal
  5        , deptno
  6     from emp
  7    order by ename
  8  )
  9  , top3 as
 10  (select *
 11     from ordered_emps
 12    where rownum &lt;= 3
 13  )
 14  select *
 15    from ordered_emps
 16  /

ENAME      JOB              SAL     DEPTNO
---------- --------- ---------- ----------
ADAMS      CLERK           1100         20
ALLEN      SALESMAN        1600         30
BLAKE      MANAGER         2850         30
CLARK      MANAGER         2450         10
FORD       ANALYST         3000         20
JAMES      CLERK            950         30
JONES      MANAGER         2975         20
KING       PRESIDENT       5000         10
MARTIN     SALESMAN        1250         30
MILLER     CLERK           1300         10
SCOTT      ANALYST         3000         20
SMITH      CLERK            800         20
TURNER     SALESMAN        1500         30
WARD       SALESMAN        1250         30

14 rows selected.

As you can see, the “Top3″ named query is not used, and there is no exception.

Thanks

Thanks to Suzanne and Kaj for discovering this little gem. See you both week next for the second part of the 7Up workshop!

Documentation

Oracle 11g on Subquery Factoring

Oracle 10g on Subquery Factoring

 

 

Share.

About Author

2 Comments

  1. Neither did I, until it was pointed out to me yesterday. ;-)
    Client Versions? Do you have more information on this?

  2. > This requirement is no longer present
    So it isn’t, I never noticed.

    The other thing to note is that if you use the same named query multiple times, certain client versions might not like it.