1、概念
游标是指向SQL处理的内存区的句柄或指针。当使用一个PL/SQL块来执行DML语句或只返回一行结果的SELECT语句时,系统将自动创建一个隐式游标。如果SQL语句返回多个结果,就必须创建一个显示游标。
--游标的属性
--(1)cur_name%rowcount :指出处理的行数
-- (2) cur_name%found :处理了一行或多行返回TRUE否则FALSE 如 WHILE CUR%FOUND中
--(3)cur_name%notfound :如果没有处理行返回TRUE,否则FALSE 如 EXIT WHEN CUR%NOTFOUND
--(4)cur_name%isopen :如果处理之后不关闭游标,则为TRUE,关闭后为FALSE。发生在隐式游标中时
-- 总是为FALSE;
2、隐式游标例程
declare tname student.name%type; tage student.age%type; begin select name,age into tname,tage from student where id = 'S001'; --返回零行货多行,执行报错 dbms_output.put_line('name= '||tname||'age= '||tname); end
3、显示游标
3.1、定义游标
--cursor cursor_name is select _statement; cursor c_stu is select from student; c_stu sys_refcursor;--系统游标 --定义游标(3) --先在包中定义游标,及用于检索的结构体, --这里的结构体相当于 游标%rowtype create or replace package p_stu as type c_su is ref cursor; type rc_stu is record( name student.name%type, age student.age%type ); end; --使用包中的游标 declare c_student p_stu.c_stu; crw_stu p_stu.rc_stu; begin open c_student for select name,age from student; loop fetch c_student into crw_stu; exit when c_student%notfound; dbms_output.put_line('name= '||crw_stu.name||' age= '||crw_stu.age); end loop; end;
游标使用案例
declare --定义一个游标 cursor c_stu is select name,age from student; --定义一个游标变量 cw_stu c_stu%rowtype; begin for cw_stu in c_stu loop dbms_output.put_line('姓名='||cw_stu.name||' 年龄='||cw_stu.age); end loop; end
--使用 fetch 必须明确打开和关闭游标 declare cursor c_stu is select name,age from student; --定义一个游标变量 cw_stu c_stu%rowtype; begin open c_stu; loop fetch c_stu into cw_stu; exit when c_stu%notfound; dbms_output.put_line('姓名='||cw_stu.name||' 年龄='||cw_stu.age); end loop close c_stu; end
--使用 while fetch 遍历数据 %found属性 declare cursor c_stu is select name,age from student; cw_stu c_stu%rowtype; begin open c_stu; fetch c_stu into cw_stu; while c_stu%found loop dbms_output.put_line('姓名='||cw_stu.name||' 年龄='||cw_stu.age); end loop close c_stu; end
3.3、在存储过程中返回游标
-- 注意:在declare块中使用存储过程返回的游标时:
-- (1)不能定义系统游标变量,编译错误。如:cw_Stu C_Stu%rowtype;
-- (2)可以使用结构体变量,但不能使用for循环如:for rw_stu in c_stu loop
-- 将提示 c_stu '不是过程或尚未定义'。
-- (3)游标不可显示打开或关闭,如 open c_stu;表达式类型错误。
create or replace procedure ( CID in varchar2, Cur_Stu out sys_refcursor--不能定义系统变量 )as begin open Cur_Stu for select name,age from student where ClassId=Id; end ;
-- 使用
-- 测试结果:
-- (1)不能定义系统游标变量,编译错误。如:cw_Stu C_Stu%rowtype;
-- (2)可以使用结构体变量,但不能使用for循环如:for rw_stu in c_stu loop
-- 将提示 c_stu '不是过程或尚未定义'。
-- (3)游标不可显示打开或关闭,如 open c_stu;表达式类型错误。
declare C_Stu Sys_RefCursor; type rec_stu is record( tname student.name%type; tage student.age%type ); rw_stu rec_stu; begin pro_syscur('C001',c_stu); loop --也可以写成 fetch c_stu into rw_stu.tname,rw_stu.tage; --或直接定义表字段类型变量 fetch c_stu into rw_stu; exit when c_stu%notfound; dbms_output.put_line('姓名='||rw_stu.tname||' 年龄='||rw_stu.tage); end loop; end
(1)返回自定义游标
--第一步,在包中定义游标,及用于遍历的结构体 create or replace package pack_stu as type c_pubsur is ref cursor; type re_stu is record( tname student.name%type, tage student.age%type ); num number; end --第二步,将存储过程的返回类型设为上面包中游标类型 create or replace procedure p_stu( cid in varchar2,c_s out pack_stu.c_pubsur )as begin open c_s for select name,age from student where classid=cid; --第三步,使用游标,注意事项与系统游标一致。 end declare c_stu pack_stu.c_pubsur; cw_stu pack_stu.re_stu; begin p_stu('D001',c_stu); loop fetch c_stu into cw_stu; exit when c_stu%notfound; dbms_output.put_line('姓名='||cw_stu.tname||' 年龄='||cw_stu.tage); end loop end