在 PL/SQL 中循环使用游标

Posted

技术标签:

【中文标题】在 PL/SQL 中循环使用游标【英文标题】:Using cursors in loop in PL/SQL 【发布时间】:2020-11-08 15:14:46 【问题描述】:

我有一个包含 3 列的表。第一列的名称是 id,第二列的名称是 parent_id,第三列的名称是表达式。我想要做的是在表达式列中搜索 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(table 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;

【问题讨论】:

【参考方案1】:

如果我正确理解了您的描述,您正在寻找它,父系中任何行的指定 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;

参见fiddle here,它还包含一个带有嵌套函数和一个带有光标的匿名块实现。

【讨论】:

不客气。如果答案已解决或大大有助于解决您的问题,请接受答案。这极大地帮助了将来可能遇到相同问题的其他人。请不要将已成功回答的问题置于未回答/未解决状态。

以上是关于在 PL/SQL 中循环使用游标的主要内容,如果未能解决你的问题,请参考以下文章

使用 FETCH 的 PL/SQL 游标 FOR 循环

pl / sql如何使用带有游标的for循环进行更新操作

Pl/Sql 在for循环中打开游标

PL/SQL:游标使用中的 ORA-01001

PL/SQL控制语句(循环控制语句)

实验七:PL/SQL编程基础