Оценка короткого замыкания CASE и COALESCE работает с последовательностями в PL / SQL, но не в SQL
Выполнена ли оценка короткого замыкания, описанная в документации дляCASE
а такжеCOALESCE()
применять к последовательностям при использовании в SQL? Это, кажется, не происходит.
Оракулдокументация поCASE
говорится, что:
База данных Oracle использует оценку короткого замыкания. Для простогоCASE
выражение ... Oracle никогда не оценивает сравнение_экспресс, если предыдущий сравнение_экспресс равно expr. Для искомого выражения CASE база данных ... никогда не оценивает условие, если предыдущее условие было истинным.
Аналогично дляCOALESCE()
документация говорится, что:
База данных Oracle использует оценку короткого замыкания. База данных оценивает каждое значение expr и определяет, является ли оно NULL, вместо того, чтобы оценивать все значения expr, прежде чем определять, является ли какое-либо из них NULL.
При вызове последовательности из SQL это не так; как видите, короткое замыкание не происходит, и последовательность увеличивается.
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
Однако при вызове из PL / SQL последовательностьне увеличивается:
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
Вызов последовательности в SQL из PL / SQL приводит к тем же результатам, что и в SQL:
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
Кажется, в документации нет ничего об этом;Руководство администратора по управлению последовательностями, ссылка на язык SQL для последовательности psuedocolumns, ссылка на язык PL / SQL в CURRVAL и NEXTVAL или жеобзор концепций базы данных последовательностей.
Оценка короткого замыканияCASE
а такжеCOALESCE()
происходят для последовательностей при использовании в SQL? Это задокументировано?
Мы на 11.2.0.3.5, если это интересно.