Does the short-circuit evaluation described in the documentation for CASE and COALESCE() apply to sequences when used in SQL? This does not appear
Explanation of why the short-circuit evaluation does not apply to sequences might be the following. What is a sequence? Putting internals aside, it's a combination of sequence definition(record in seq$ data dictionary table) and some internal SGA component, it's not a function and might be considered, although the documentation does not state it directly(but execution plan does) as row source. And every time a sequence is being referenced directly in the select list of a query, it has to be evaluated by the optimizer when it searches for optimal execution plan. During the process of forming an optimal execution plan a sequence gets incremented if nextval pseudocolumn is referenced:
SQL> create sequence seq1;
Sequence created
Here is our sequence:
SQL> select o.obj#
2 , o.name
3 , s.increment$
4 , s.minvalue
5 , s.maxvalue
6 , s.cache
7 from sys.seq$ s
8 join sys.obj$ o
9 on (o.obj# = s.obj#)
10 where o.name = 'SEQ1'
11 ;
OBJ# NAME INCREMENT$ MINVALUE MAXVALUE CACHE
---------- ------- ---------- ---------- ---------- ----------
94442 SEQ1 1 1 1E28 20
Lets trace below query, and also take a look at its execution plan
SQL> ALTER SESSION SET EVENTS '10046 trace name context forever, level 4';
Session altered
SQL> select case
2 when 1 = 1 then 1
3 when 2 = 1 then seq1.nextval
4 end as res
5 from dual;
RES
----------
1
/* sequence got incremented by 1 */
SQL> select seq1.currval from dual;
CURRVAL
----------
3
Trace file information:
STAT #1016171528 id=1 cnt=1 pid=0 pos=1 obj=94442 op='SEQUENCE SEQ1 ...
STAT #1016171528 id=2 cnt=1 pid=1 pos=1 obj=0 op='FAST DUAL ...
CLOSE #1016171528:c=0,e=12,dep=0,type=0,tim=12896600071500 /* close the cursor */
The execution plan will show us basically the same:
SQL> explain plan for select case
2 when 1 = 1 then 1
3 else seq1.nextval
4 end
5 from dual
6 /
Explained
Executed in 0 seconds
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
---------------------------------------------------------------
Plan hash value: 51561390
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | SEQUENCE | SEQ1 | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
9 rows selected
Executed in 0.172 seconds
In terms of evaluation, referencing a sequence directly in a query, roughly the same as including a correlated sub-query. That correlated sub-query will always be evaluated by the optimizer:
SQL> explain plan for select case
2 when 1 = 1 then 1
3 when 2 = 1 then (select 1
4 from dual)
5 end as res
6 from dual;
Explained
Executed in 0 seconds
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------
Plan hash value: 1317351201
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
9 rows selected
Executed in 0.063 seconds
We can see that dual table has been included in the execution plan twice.
The analogy with a sub-query was made in a rush. There are more differences than similarities, of course. Sequences are absolutely different mechanisms. But, a sequences are viewed by the optimizer as a row source, and as long as it doesn't see the nextval pseudocolumn of a sequence being directly referenced in the select list of a top-level query, it won't evaluate the sequence, otherwise sequence will be incremented, whether a short-circuit evaluation logic is being used or not. PL/SQL engine,obviously, (starting from Oracle 11g r1) has a different way to access a sequence value. Should be noted that in previous 11gR1 versions of RDBMS we should write a query to reference a sequence in PL/SQL block, which PL/SQL engine sent directly to the SQL engine.
The answer to the "why a sequence gets incremented during generating an execution plan by the optimizer" question, lies in the internal implementation of sequences.