Последовательность и регистр в select в oracle - PullRequest
5 голосов
/ 18 октября 2011

Я пытаюсь выполнить этот запрос (в oracle), но у меня есть некоторые проблемы:

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; 

Я получаю следующие результаты:

COL_1
----------------------------------------------
191next20
192curr
193curr
194next20
195curr
196curr
197next10
198next20
199next10
200curr
201next20
202curr
203next20
204next10
205next20
206next10
207next10

И вот чтоЯ думаю, что они должны быть:

COL_1
----------------------------------------------
191next20
192curr
193curr
194next20
194curr
194curr
197next10
198next20
199next10
199curr
201next20
201curr
203next20
204next10
205next20
206next10
207next10

Итак, почему я получаю следующее значение последовательности также, когда я должен иметь текущее значение, а не только когда регистр выбирает следующее значение?Да, это можно сделать с помощью сценария plsql, но я не могу.

Спасибо!

Ответы [ 2 ]

10 голосов
/ 18 октября 2011

Nextval и currval не являются функциями, но являются " псевдостолбцами последовательности ".

"В одной инструкции SQL, содержащей ссылку на NEXTVAL, Oracle увеличивает последовательность один раз: для каждой строки, возвращаемой внешним блоком запроса инструкции SELECT. Такой запрос блок может появиться в следующих местах. ... "(выделение выделено) [ Справочник по языку базы данных Oracle SQL ," Как использовать значения последовательности "]

Другими словами, seq.nextval - это не функция с побочным эффектом, а псевдостолбец, который имеет конкретное значение в строке. При наличии единственной ссылки на seq.nextval значение увеличивается для каждой строки независимо от того, используется это значение или нет. Результат, который видит OP, свойственен последовательностям, а не выражениям. Например, то же самое с декодированием:

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
1 голос
/ 18 октября 2011

Интересно.Согласно Oracle docs :

Операторы в предложении WHEN могут изменять базу данных и вызывать недетерминированные функции.Механизм переключения не существует, как в операторе C switch

. Обратите внимание, что в операторе «true» WHEN не сказано операторов.Таким образом, даже если утверждение when ложно, nextval сработает:

select
case when 1=0 then 'next ' || seq_id.nextval
     when 1=1 then 'curr ' || seq_id.currval
end col1
from dual;

Я должен признать, что это отличается от того, что я ожидал.

РЕДАКТИРОВАТЬ: См. Ответ от ShannonSeverance

...