Does the short-circuit evaluation described in the documentation for CASE
and COALESCE()
apply to sequences when used in SQL? This does not appear to be happening.
The Oracle documentation on CASE
states that:
Oracle Database uses short-circuit evaluation. For a simple
CASE
expression... Oracle never evaluates a comparison_expr if a previous comparison_expr is equal to expr. For a searched CASE expression, the database... never evaluates a condition if the previous condition was true.
Similarly for COALESCE()
the documentation states that:
Oracle Database uses short-circuit evaluation. The database evaluates each expr value and determines whether it is NULL, rather than evaluating all of the expr values before determining whether any of them is NULL.
When calling a sequence from SQL this does not appear to be the case; as you can see no short circuiting occurs and the sequence is incremented.
SQL> create sequence tmp_test_seq start with 1 increment by 1;
SQL> select tmp_test_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select tmp_test_seq.currval from dual;
CURRVAL
----------
1
SQL> select coalesce(1, tmp_test_seq.nextval) from dual;
COALESCE(1,TMP_TEST_SEQ.NEXTVAL)
--------------------------------
1
SQL> select tmp_test_seq.currval from dual;
CURRVAL
----------
2
SQL> select case when 1 = 1 then 1 else tmp_test_seq.nextval end as s from dual;
S
----------
1
SQL> select tmp_test_seq.currval from dual;
CURRVAL
----------
3
However, when calling from PL/SQL the sequence is not incremented:
SQL> create sequence tmp_test_seq start with 1 increment by 1;
SQL> declare
2 i number;
3 begin
4 i := tmp_test_seq.nextval;
5 dbms_output.put_line(tmp_test_seq.currval);
6 i := coalesce(1, tmp_test_seq.nextval);
7 dbms_output.put_line(i);
8 dbms_output.put_line(tmp_test_seq.currval);
9 i := case when 1 = 1 then 1 else tmp_test_seq.nextval end;
10 dbms_output.put_line(i);
11 dbms_output.put_line(tmp_test_seq.currval);
12 end;
13 /
1
1
1
1
1
SQL> select tmp_test_seq.nextval from dual;
NEXTVAL
----------
2
Calling the sequence in SQL from PL/SQL the same results as with SQL happens:
SQL> create sequence tmp_test_seq start with 1 increment by 1;
SQL> declare
2 i number;
3 begin
4 select tmp_test_seq.nextval into i from dual;
5 dbms_output.put_line(tmp_test_seq.currval);
6 select coalesce(1, tmp_test_seq.nextval) into i from dual;
7 dbms_output.put_line(i);
8 dbms_output.put_line(tmp_test_seq.currval);
9 select case when 1 = 1 then 1 else tmp_test_seq.nextval end into i
10 from dual;
11 dbms_output.put_line(i);
12 dbms_output.put_line(tmp_test_seq.currval);
13 end;
14 /
1
1
2
1
3
There doesn't seem to be anything in the documentation about this; the Administrator's guide for managing sequences, the SQL language reference on sequence psuedocolumns, the PL/SQL language reference on CURRVAL and NEXTVAL or the database concepts overview of sequences.
Does the short-circuit evaluation of CASE
and COALESCE()
occur for sequences when used in SQL? Is this documented?
We're on 11.2.0.3.5 if it's of interest.