Я создаю вложенное дерево, и я должен получить данные для следующей строки в курсоре, с помощью Oracle. И мне все еще нужна текущая строка, таким образом, цикличное выполнение вперед не является решением. Пример:
OPEN emp_cv FOR sql_stmt;
LOOP
FETCH emp_cv INTO v_rcod,v_rname,v_level;
EXIT WHEN emp_cv%NOTFOUND;
/*here lies the code for getting v_next_level*/
if v_next_level > v_level then
/*code here*/
elsif v_next_level < v_level then
/*code here*/
else
/*code here*/
end if;
END LOOP;
CLOSE emp_cv;
Использование функций LEAD и LAG
LEAD может вычислять выражение для следующих строк (строк, которые будут идти после текущей строки) и возвращать значение в текущую строку . Общий синтаксис LEAD показан ниже:
LEAD (sql_expr, offset, default) OVER (analytic_clause)
sql_expr - это выражение, вычисляемое из первой строки.
смещение - это индекс ведущей строки относительно текущей строки. Смещение - положительное целое число со значением по умолчанию 1.
default - это значение, возвращаемое, если указывает на строку за пределами раздела диапазон.
Синтаксис LAG аналогичен, за исключением того, что смещение для LAG переходит в предыдущие строки.
SELECT deptno, empno, sal,
LEAD(sal, 1, 0) OVER (PARTITION BY dept ORDER BY sal DESC) NEXT_LOW_SAL,
LAG(sal, 1, 0) OVER (PARTITION BY dept ORDER BY sal DESC) PREV_HIGH_SAL
FROM emp
WHERE deptno IN (10, 20)
ORDER BY deptno, sal DESC;
DEPTNO EMPNO SAL NEXT_LOWER_SAL PREV_HIGHER_SAL
------- ------ ----- -------------- ---------------
10 7839 5000 2450 0
10 7782 2450 1300 5000
10 7934 1300 0 2450
20 7788 3000 3000 0
20 7902 3000 2975 3000
20 7566 2975 1100 3000
20 7876 1100 800 2975
20 7369 800 0 1100
8 rows selected.
было бы лучше сохранить предыдущий уровень и использовать его. что-то вроде
/* set to a value lesser than the lowest value possible for level
am assuming 0 is the lowest value possible */
v_previous_level := -1;
OPEN emp_cv FOR sql_stmt;
LOOP
FETCH emp_cv INTO v_rcod,v_rname,v_level;
EXIT WHEN emp_cv%NOTFOUND;
/* you'd probably have to update v_previous_level in one of
these conditions (depends on your logic) */
if v_previous_level > v_level then
/*code here*/
elsif v_previous_level < v_level then
/*code here*/
else
/*code here*/
end if;
END LOOP;
CLOSE emp_cv;
Я так и сделал. Я строю дерево на шаг назад. Я должен проверить первую итерацию.
OPEN emp_cv FOR sql_stmt;
LOOP
if emp_cv%notfound then
/*some code*/
exit;
end if;
FETCH emp_cv INTO v_new_level;
if not b_first_time then
if v_new_level > v_level then
/*some code*/
elsif v_new_level < v_level then
/*some code*/
else
/*code*/
end if;
else
b_first_time:=false;
end if;
v_level:=v_new_level;
END LOOP;
CLOSE emp_cv;