Plsql 在PL/SQL中使用循环游标

Plsql 在PL/SQL中使用循环游标,plsql,cursor,Plsql,Cursor,我有一个包含3列的表。第一列名称是id,第二列的名称是parent_id,第三列的名称是expression。我要做的是在expression列中搜索id。例如,我发送id值,然后如果parent_id列有值,我要发送parent_id值,并检查expression列是否有“E”。如果它有空值,并且结果有parent_id,则我要发送parent_id值,再次检查表达式列是否有“E”。如果表达式列有类似“E”的值,我将变量resultValue更新为1并结束循环 我的表A:它应该返回result

我有一个包含3列的表。第一列名称是id,第二列的名称是parent_id,第三列的名称是expression。我要做的是在expression列中搜索id。例如,我发送id值,然后如果parent_id列有值,我要发送parent_id值,并检查expression列是否有“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
id  |parent_id|expression
30  |null     | null
20  |30       | null
10  |null     | null
我的表C:它应该返回resultValue=0

id  |parent_id|expression
30  |null     | null
20  |30       | null
10  |20       | null
id  |parent_id|expression
30  |null     | null
20  |30       | null
10  |null     | null
如果第一个发送id(10)不包含父id(表C),则resultValue变量应为0。如果我找到“E”表达式,任何父行resultValue变量都应该返回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;
声明
结果值编号:=0;
光标c(v_id编号)
是
选择id_值、id_父项、来自学生的表达式,其中id_值=v_id;
多付手续费
是
id_值编号;
身份证号码;
表达VARCHAR2(20);
开始
环
将c读入id\u值、id\u父项、表达式;
出口
当未找到c%时;
若id_parent为NULL,表达式为NULL,则
出口
如果结束;
如果id\u parent不为NULL,则
关闭c;
打开c(id\U父级);
如果id\u parent为NULL且表达式为'X'或id\u parent为NULL且表达式为'X',则
结果值:=1;
出口
如果结束;
端环;
超额支付的期末打印费;
开始
开放c(22);
多付印刷费;
DBMS|u OUTPUT.PUT_行('MyResultValue为:'|| resultValue);
关闭c;
结束;

如果我正确理解了您的描述,您将看到它父级中任何行的指定id在列表达式中包含“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 = &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;

请参阅,它还包含一个带嵌套函数的匿名块实现和一个带游标的匿名块实现。

非常感谢您,我们非常欢迎您。如果答案已解决或实质上有助于解决您的问题,请接受答案。这对将来可能有同样问题的人有很大帮助。请不要将已成功回答的问题保留为未回答/未解决状态。