如何在PL/SQL中连续循环多个游标

问题描述 投票:0回答:1

这可能很简单,但我在网上找不到好的例子。我有 5 个游标,我想连续迭代(循环遍历所有游标 1,然后循环遍历所有游标 2,等等)。需要注意的是,我(相信我)需要同时打开所有游标,因为我正在删除循环中的记录,这会影响后面游标中 select 语句的输出...我希望游标反映程序执行开始时的输出,而不是光标循环开始时的输出。

示例:

DECLARE 

CURSOR A IS SELECT * FROM tableA;
CURSOR B IS SELECT * FROM tableB;
CURSOR C IS SELECT * FROM tableC;

rowA A%rowtype;
rowB B%rowtype;
rowC C%rowtype;

BEGIN
 OPEN A;
 OPEN B;
 OPEN C;

 FOR record IN A LOOP
  FETCH A INTO rowA
  DELETE FROM ...
 END LOOP;
 CLOSE A;

 FOR record IN B LOOP
  FETCH B INTO rowB
  DELETE FROM ...
 END LOOP;
 CLOSE B;

 etc

END;



尝试上面的代码片段,我意识到指定“FOR record IN X”会隐式地再次打开游标,这会引发错误。但是,如果我不添加我想要循环的游标,循环如何知道我要循环的游标,因为我打开了 3 个游标?

再次,我需要在循环之前打开所有游标,因为我要删除循环中影响游标的 select 语句返回内容的行。当到达游标C的循环时,如果我当时打开它,游标将不会返回任何行,这不是我想要的。

sql oracle plsql
1个回答
0
投票

此示例基于 Scott 的样本

EMP
DEPT
表。有两个光标;其中之一显示部门并删除在这些部门工作的员工。另一个显示(或者,正在尝试显示)员工。

样本数据:

SQL> set serveroutput on
SQL> select deptno, dname from dept order by deptno;

    DEPTNO DNAME
---------- --------------
        10 ACCOUNTING
        20 RESEARCH
        30 SALES
        40 OPERATIONS

SQL> select deptno, empno, ename from emp order by deptno, ename;

    DEPTNO      EMPNO ENAME
---------- ---------- ----------
        10       7782 CLARK
        10       7839 KING
        10       7934 MILLER
        20       7876 ADAMS
        20       7902 FORD
        20       7566 JONES
        20       7788 SCOTT
        20       7369 SMITH
        30       7499 ALLEN
        30       7698 BLAKE
        30       7900 JAMES
        30       7654 MARTIN
        30       7844 TURNER
        30       7521 WARD

14 rows selected.

在第一个示例中,我正在打开 - 然后逐一处理 - 游标(第 9 行和第 20 行):

SQL> declare
  2    cursor cur_d is select deptno, dname from dept order by deptno;
  3    cur_dr cur_d%rowtype;
  4
  5    cursor cur_e is select deptno, empno, ename from emp
  6      order by deptno, ename;
  7    cur_er cur_e%rowtype;
  8  begin
  9    open cur_d;
 10    dbms_output.put_line('Departments ----------');
 11    loop
 12      fetch cur_d into cur_dr;
 13      exit when cur_d%notfound;
 14      dbms_output.put_line(cur_dr.deptno ||' - '|| cur_dr.dname);
 15      delete from emp where deptno = cur_dr.deptno;
 16      dbms_output.put_line('Deleted ' || sql%rowcount ||' employees');
 17    end loop;
 18    close cur_d;
 19
 20    open cur_e;
 21    dbms_output.put_line('Employees ----------');
 22    loop
 23      fetch cur_e into cur_er;
 24      exit when cur_e%notfound;
 25      dbms_output.put_line(cur_er.deptno ||' - '|| cur_er.ename);
 26    end loop;
 27    close cur_e;
 28  end;
 29  /

输出显示我删除的部门列表和员工数量。然而,根本没有显示任何员工,因为他们在cur_e

打开之前被删除了:

Departments ---------- 10 - ACCOUNTING Deleted 3 employees 20 - RESEARCH Deleted 5 employees 30 - SALES Deleted 6 employees 40 - OPERATIONS Deleted 0 employees Employees ---------- PL/SQL procedure successfully completed.
最终结果,

emp

表为空:

SQL> select deptno, ename from emp order by deptno, ename; no rows selected SQL>


另一个示例在开头打开两个光标(第 9 行和第 10 行):

SQL> rollback; Rollback complete. SQL> declare 2 cursor cur_d is select deptno, dname from dept order by deptno; 3 cur_dr cur_d%rowtype; 4 5 cursor cur_e is select deptno, empno, ename from emp 6 order by deptno, ename; 7 cur_er cur_e%rowtype; 8 begin 9 open cur_d; 10 open cur_e; 11 dbms_output.put_line('Departments ----------'); 12 loop 13 fetch cur_d into cur_dr; 14 exit when cur_d%notfound; 15 dbms_output.put_line(cur_dr.deptno ||' - '|| cur_dr.dname); 16 delete from emp where deptno = cur_dr.deptno; 17 dbms_output.put_line('Deleted ' || sql%rowcount ||' employees'); 18 end loop; 19 close cur_d; 20 21 dbms_output.put_line('Employees ----------'); 22 loop 23 fetch cur_e into cur_er; 24 exit when cur_e%notfound; 25 dbms_output.put_line(cur_er.deptno ||' - '|| cur_er.ename); 26 end loop; 27 close cur_e; 28 end; 29 /
部门像以前一样显示,员工被删除,但它们也

显示,因为在删除员工之前打开了cur_e

Departments ---------- 10 - ACCOUNTING Deleted 3 employees 20 - RESEARCH Deleted 5 employees 30 - SALES Deleted 6 employees 40 - OPERATIONS Deleted 0 employees
全体员工如下:

Employees ---------- 10 - CLARK 10 - KING 10 - MILLER 20 - ADAMS 20 - FORD 20 - JONES 20 - SCOTT 20 - SMITH 30 - ALLEN 30 - BLAKE 30 - JAMES 30 - MARTIN 30 - TURNER 30 - WARD PL/SQL procedure successfully completed.
最终结果是一样的:

emp

表为空:

SQL> select deptno, ename from emp order by deptno, ename; no rows selected SQL>
    
© www.soinside.com 2019 - 2024. All rights reserved.