I'm trying to do this query (in oracle) but I have some problems:
SELECT CASE
WHEN deptno = '10' THEN scott.seq.nextval
|| 'next10'
WHEN deptno = '20' THEN scott.seqnextval
|| 'next20'
WHEN deptno = '30' THEN scott.seq.currval
|| 'curr'
END col_1
FROM scott.emp;
I'm getting this results:
COL_1 ---------------------------------------------- 191next20 192curr 193curr 194next20 195curr 196curr 197next10 198next20 199next10 200curr 201next20 202curr 203next20 204next10 205next20 206next10 207next10
And this is what I think they should be:
COL_1 ---------------------------------------------- 191next20 192curr 193curr 194next20 194curr 194curr 197next10 198next20 199next10 199curr 201next20 201curr 203next20 204next10 205next20 206next10 207next10
So, why i get the next value of the sequence also when I should have the current value and not only when the case selects the next value? Yeah, this could be done with a plsql script but I can't.
Thanks you!
Introduction to Oracle CASE expression You can use a CASE expression in any statement or clause that accepts a valid expression. For example, you can use the CASE expression in statements such as SELECT , UPDATE , or DELETE , and in clauses like SELECT , WHERE , HAVING , and ORDDER BY .
CASE Statement. The CASE statement selects a sequence of statements to execute. To select the sequence, the CASE statement uses a selector (an expression whose value is used to select one of several alternatives) or, in the searched CASE statement, multiple search conditions.
CURRVAL. returns the current value of a sequence. NEXTVAL. increments the sequence and returns the next value.
The Oracle NEXTVAL function is used to retrieve the next value in a sequence. The Oracle NEXTVAL function must be called before calling the CURRVAL function, or an error will be thrown.
Nextval
and currval
are not functions, but are "Sequence Pseudocolumns".
"Within a single SQL statement containing a reference to NEXTVAL, Oracle increments the sequence once: For each row returned by the outer query block of a SELECT statement. Such a query block can appear in the following places. ..." (emphasis added) [Oracle Database SQL Language Reference, "How to Use Sequence Values"]
In other words, seq.nextval
is not a function with a side affect, but a pseudocolumn that has a particular value per row. Once there is a single reference to seq.nextval
, the value increments for every row, whether or not the value is used. The outcome OP is seeing is a peculiar to sequences, not case expressions. For example, same thing with decode:
SQL> select decode(deptno
2 , 10, seq.nextval || 'next10'
3 , 20, seq.nextval || 'next20'
4 , 30, seq.currval || 'curr30')
5 from emp;
DECODE(DEPTNO,10,SEQ.NEXTVAL||'NEXT10',20,SEQ.
----------------------------------------------
35next20
36curr30
37curr30
38next20
39curr30
40curr30
41next10
42next20
43next10
44curr30
45next20
46curr30
47next20
48next10
Interesting. Per the Oracle docs:
The statements in a WHEN clause can modify the database and call non-deterministic functions. There is no fall-through mechanism as in the C switch statement
Notice it doesn't say the statements in the "true" WHEN clause. So even if the when statement is false, the nextval will fire:
select
case when 1=0 then 'next ' || seq_id.nextval
when 1=1 then 'curr ' || seq_id.currval
end col1
from dual;
I must admit this is different than I expected.
EDIT: See answer from ShannonSeverance
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With