#plsql #cursor
#plsql #курсор
Вопрос:
У меня есть таблица, которая содержит 3 столбца.Имя первого столбца — id , имя второго столбца — parent_id, а третье — выражение.Что я хочу сделать, так это выполнить поиск в столбце выражения для идентификатора.Например, я отправляю значение id, затем, если столбец parent_id имеет значение, я хочу отправить значение parent_id и хочу проверить, имеет столбец выражения ‘E’ или нет.Если он имеет нулевое значение, а результат имеет parent_id, тогда я хочу отправить значение parent_id и снова хочу проверить, имеет столбец выражения ‘E’ или нет.Если столбец выражения имеет значение, подобное ‘E’, я обновил переменную resultValue как 1 и завершил цикл.
моя таблица A: она должна возвращать resultValue =1
id |parent_id|expression
123 |null | null
45 |123 | 'E'
22 |45 | null
моя таблица B: она должна возвращать resultValue = 0
id |parent_id|expression
30 |null | null
20 |30 | null
10 |20 | null
моя таблица C: она должна возвращать resultValue = 0
id |parent_id|expression
30 |null | null
20 |30 | null
10 |null | null
Если первая отправка id(10) не содержит parent_id(таблица C), переменная resultValue должна быть равна 0. Если я нахожу выражение ‘E’, любая переменная результирующего значения родительской строки должна возвращать 1.
Я создал блок кода с курсором.Впервые я использовал курсор.Я не уверен, что использование курсора с такой проблемой — хорошая идея или нет.Мой код запущен, но открыть курсор, затем закрыть курсор, а затем снова открыть курсор, это хорошая идея?
DECLARE
resultValue NUMBER := 0;
CURSOR c(v_id NUMBER )
IS
SELECT id_value, id_parent, expression FROM students WHERE id_value = v_id;
PROCEDURE print_overpaid
IS
id_value NUMBER;
id_parent NUMBER;
expression VARCHAR2(20);
BEGIN
LOOP
FETCH c INTO id_value, id_parent, expression;
EXIT
WHEN c%NOTFOUND;
IF id_parent IS NULL AND expression IS NULL THEN
EXIT;
END IF;
IF id_parent IS NOT NULL THEN
CLOSE c;
OPEN c(id_parent);
ELSIF id_parent <> NULL AND expression = 'X' OR id_parent IS NULL AND expression = 'X' THEN
resultValue := 1;
EXIT;
END IF;
END LOOP;
END print_overpaid;
BEGIN
OPEN c(22);
print_overpaid;
DBMS_OUTPUT.PUT_LINE(' My resultValue is : ' || resultValue);
CLOSE c;
END;
Ответ №1:
Если я правильно понял ваше описание, вы хотите увидеть, что указанный идентификатор любой строки в родительском элементе содержит ‘E’ в выражении столбца. Вы правы, что закрытие и повторное открытие курсора на самом деле не очень хорошая идея. Хотя мне нравится, что вы используете вложенную процедуру. Однако на самом деле в этом нет необходимости, поскольку это можно решить с помощью одного запроса. Подход будет рекурсивным CTE, который проверяет целевую строку на ‘E’ до тех пор, пока строка не будет содержать ее или строка не будет иметь родительского элемента.
with search_for_e(id, parent_id, e_cnt) as
( select id, parent_id, case when expression = 'E' then 1 else 0 end
from exp_tbl
where id = amp;id
union all
select t.id,t.parent_id, case when t.expression = 'E' then 1 else 0 end
from search_for_e s
join exp_tbl t on (t.id = s.parent_id)
where t.parent_id is not null
and s.e_cnt = 0
)
select max(e_cnt)
from search_for_e;
Смотрите fiddle здесь, он также содержит реализацию анонимного блока с вложенной функцией и с курсором.
Комментарии:
1. Добро пожаловать. Если ответ разрешил или существенно помог решить вашу проблему, пожалуйста, примите ответ. Это очень помогает другим, у которых может возникнуть такая же проблема в будущем. Пожалуйста, не оставляйте успешно отвеченные вопросы в статусе неотвеченные / неразрешенные.