【发布时间】:2013-12-31 06:40:19
【问题描述】:
CASE 和 COALESCE() 文档中描述的短路评估是否适用于在 SQL 中使用的序列?这似乎没有发生。
Oracle documentation on CASE 声明:
Oracle 数据库使用短路评估。对于一个简单的
CASE表达式...如果先前的 compare_expr 等于 expr,Oracle 永远不会计算 compare_expr。对于搜索到的 CASE 表达式,如果前一个条件为真,数据库...从不计算条件。
COALESCE()the documentation 同样声明:
Oracle 数据库使用短路评估。数据库评估每个 expr 值并确定它是否为 NULL,而不是在确定它们中的任何一个是否为 NULL 之前评估所有 expr 值。
从 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
从 PL/SQL 调用 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
文档中似乎没有关于此的任何内容; the Administrator's guide for managing sequences、the SQL language reference on sequence psuedocolumns、the PL/SQL language reference on CURRVAL and NEXTVAL 或 the database concepts overview of sequences。
CASE 和 COALESCE() 在 SQL 中使用时是否会发生序列的短路评估?这有记录吗?
如果感兴趣,我们将在 11.2.0.3.5 上进行。
【问题讨论】:
-
在 SQL Server 中测试。
NEXT VALUE FOR function cannot be used within CASE, CHOOSE, COALESCE, IIF, ISNULL and NULLIF.我猜这是避免它的一种方法! -
我猜这是 Metalink 的问题。
-
如果以前没有人注意到这一点,我会感到惊讶...@Alan。我设法在 metalink 上找到了 2331433,它看起来很相似(ish),但只在 CASE 而不是 COALESCE 上。我也喜欢 Oracle 的回复,但没有那么有帮助。
标签: sql oracle plsql oracle11g sequence