数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

PL/SQL-嵌套游标cursor


发布日期:2020年08月09日
 
PL/SQL-嵌套游标cursor

cursor() 函数可以将一个查询结果集封装成一个类似 REF CURSOR 的游标变量可以 FETCH 记录也可以作为 REF CURSOR 类型的参数进行传递它被称为嵌套游标(nested cursor)

FETCH 记录

我们先看一下测试表 test 和 test 的数据

SQL> select * from test;

A

SQL> select * from test;

ID NAME

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

我们可能会发出这样一个查询

SQL> select id name (select a from test where a = testid)

from test;

select id name (select a from test where a = testid)

*

ERROR 位于第 行:

ORA: 单行子查询返回多个行

因为表 test 中有两条 a= 的记录所以这个查询执行失败了但有时候我们确实需要这样的查询怎么办呢?你可以试试 cursor() 函数

SQL> set serveroutput on

SQL> declare

cursor cur_test is

select id name cursor(select a from test where a = testid)

from test;

rec_test test%rowtype;

cur_test sys_refcursor;

rec_test test%rowtype;

begin

open cur_test;

loop

fetch cur_test into rec_testid rec_testname cur_test;

exit when cur_test%notfound;

dbms_outputput_line(rec_testid: || rec_testid || | rec_testname: || rec_testname);

这里不需要再显式 OPEN 游标 cur_test也不需要显式关闭

loop

fetch cur_test into rec_test;

exit when cur_test%notfound;

dbms_outputput_line( rec_testa: || rec_testa );

end loop;

end loop;

close cur_test;

end;

/

rec_testid: | rec_testname: yuechaotian

rec_testa:

rec_testa:

rec_testid: | rec_testname: yuechaotian

rec_testa:

rec_testid: | rec_testname: yuechaotian

rec_testa:

rec_testid: | rec_testname: yuechaotian

rec_testid: | rec_testname: yuechaotian

PL/SQL 过程已成功完成

怎么样?达到你的目的了吧我们再看一个嵌套了两个 cursor() 函数的例子

SQL> declare

嵌套定义游标

cursor cur_test is

select id name cursor(select a cursor(select * from dual)

from test

where testa = testid)

from test;

cur_test sys_refcursor;

cur_dual sys_refcursor;

rec_test test%rowtype;

rec_test test%rowtype;

rec_dual varchar();

begin

open cur_test;

loop

fetch cur_test into rec_testid rec_testname cur_test;

exit when cur_test%notfound;

dbms_outputput_line( rec_testid: || rec_testid || rec_testname: || rec_testname);

这里不需要再显式 OPEN 游标 cur_test也不需要显式关闭

loop

fetch cur_test into rec_testa cur_dual;

exit when cur_test%notfound;

dbms_outputput_line( rec_testa: || rec_testa );

这里不需要再显式 OPEN 游标 cur_dual也不需要显式关闭

loop

fetch cur_dual into rec_dual;

exit when cur_dual%notfound;

dbms_outputput_line( rec_dual: || rec_dual );

end loop;

end loop;

end loop;

close cur_test;

end;

/

rec_testid: rec_testname: yuechaotian

rec_testa:

rec_dual: X

rec_testa:

rec_dual: X

rec_testid: rec_testname: yuechaotian

rec_testa:

rec_dual: X

rec_testid: rec_testname: yuechaotian

rec_testa:

rec_dual: X

rec_testid: rec_testname: yuechaotian

rec_testid: rec_testname: yuechaotian

PL/SQL 过程已成功完成

由以上例子可以看出嵌套游标是隐式打开的它在以下情况下被关闭

显式关闭

父游标再次执行时(比如下一次循环前会先关闭嵌套游标再根据新数据重新打开)

父游标关闭时

父游标退出时

fetch 父游标出错时

传递参数

我们先看看测试表中的数据

SQL> select * from test;

ID NAME

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

yuechaotian

已选择

SQL> select * from test order by a;

A

已选择

下面我要查询 test 中的数据查询条件是 testid 在 testa 中对应的记录数比如我要查询表 testid 在 testa 中不存在的记录查询表 testid 在testa 中存在条的记录存在条的记录存在条的记录……我可以使用嵌套游标实现

SQL> create function f_count(cur_names in sys_refcursor) return number

is

v_name testname%type;

n_count number() := ;

begin

loop

fetch cur_names into v_name;

exit when cur_names%notfound;

n_count := n_count + ;

end loop;

return n_count;

end f_count;

/

函数已创建

SQL> select id name

from test

where f_count( cursor( select a from test where a = testid ) ) = ;

ID NAME

yuechaotian

yuechaotian

yuechaotian

SQL> select id name

from test

where f_count( cursor( select a from test where a = testid ) ) = ;

ID NAME

yuechaotian

yuechaotian

yuechaotian

yuechaotian

SQL> select id name

from test

where f_count( cursor( select a from test where a = testid ) ) = ;

ID NAME

yuechaotian

yuechaotian

SQL> select id name

from test

where f_count( cursor( select a from test where a = testid ) ) = ;

ID NAME

yuechaotian

上一篇:Oracle的in和not in(图)

下一篇:Oracle在数据转储时的字符集问题