1.分类:
静态游标:显式游标和隐式游标称为静态游标,因为在使用他们之前,游标的定义已经完成,不能再更改。
动态游标:游标在声明时没有设定,在打开时可以对其进行修改。分为强类型游标和弱类型游标。
强类型动态游标:在声明变量时使用return关键字定义游标的返回类型
弱类型动态游标:在声明变量时不使用return关键字定义游标的返回类型
一般动态游标有 REF CURSOR、REF CURSOR RETURN、SYS_REFCURSOR。
REF CURSOR RETURN 为强类型,REF CURSOR 为弱类型、SYS_REFCURSOR 为系统预定义(在STANDARD包中定义的)弱类型。
2.有如下的3种定义方式:
--支持记录类型
type t_cur is ref cursor return emp%rowtype;
v_cur t_cur;
type t_weak_cur is ref cursor;
v_cur2 t_weak_cur;
v_cur3 sys_refcursor;
例1:强弱cursor
declare
--定义强类型 ,返回的类型与定义的类型v_dept必须一致
type c_dept_ref is ref cursor return dept%rowtype;
cur_dept c_dept_ref;
v_dept dept%rowtype;
begin
open cur_dept for select * from dept;
--动态游标,不能使用for循环
loop
fetch cur_dept into v_dept;
exit when cur_dept%notfound ;
dbms_output.put_line(v_dept.dname);
end loop;
close cur_dept;
end;
/
--弱类型
declare
type c_cursor is ref cursor;
v_ref_cur c_cursor;
v_emprow emp%rowtype;
v_deptrow dept%rowtype;
begin
open v_ref_cur for
select * from dept;
loop
fetch v_ref_cur
into v_deptrow;
exit when v_ref_cur%notfound;
dbms_output.put_line(v_deptrow.dname);
end loop;
close v_ref_cur;
dbms_output.put_line('-------------------------');
open v_ref_cur for
select * from emp where deptno = 10;
loop
fetch v_ref_cur
into v_emprow;
exit when v_ref_cur%notfound;
dbms_output.put_line(v_emprow.ename);
end loop;
close v_ref_cur;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
/
例2:SYS_REFCURSOR
使用oracle9i提供的SYS_REFCURSOR弱类型游标,定义游标都省了....
--弱类型
declare
v_ref_cur sys_refcursor;
v_emprow emp%rowtype;
v_deptrow dept%rowtype;
begin
open v_ref_cur for
select * from dept;
loop
fetch v_ref_cur
into v_deptrow;
exit when v_ref_cur%notfound;
dbms_output.put_line(v_deptrow.dname);
end loop;
close v_ref_cur;
dbms_output.put_line('-------------------------');
open v_ref_cur for
select * from emp where deptno = 10;
loop
fetch v_ref_cur
into v_emprow;
exit when v_ref_cur%notfound;
dbms_output.put_line(v_emprow.ename);
end loop;
close v_ref_cur;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
/
我们发现,为了接受可能的v_ref类型,使用了2个变量,能不能使用一个变量来直接接受v_ref的值呢? 对于弱类型的动态游标绝对不行,为什么?
如果直接使用:
v_ref_cur sys_refcursor;
v_ref_vlaue v_ref_cur%rowtype;
是会报错,声明问题,个人理解:因为此时的动态游标返回内容都不知道,你就直接写 v_ref_vlaue v_ref_cur%rowtype; 那么v_ref_vlaue是什么类型,接受那些值,你肯定不知道,这就违反了声明的确定性了...
而如果是强类型的动态就可以这样,因为人家已经在return里面写死了类型;
例3:可作为出参/入参
declare
--强类型,支持记录类型
type t_cur is ref cursor return emp%rowtype;
v_cur t_cur;
--自定义弱类型
type t_weak_cur is ref cursor;
v_cur2 t_weak_cur;
--系统自带弱类型
v_cur3 sys_refcursor;
--使用强类型
procedure c_get_info(p_emp_cursor t_cur) is
v_emp_cur p_emp_cursor%rowtype;
begin
loop
fetch p_emp_cursor into v_emp_cur;
exit when p_emp_cursor%notfound;
dbms_output.put_line('强类型-'||v_emp_cur.ename);
end loop;
end;
--使用自定义弱类型
procedure c_get_info_weak1(p_emp_cursor t_weak_cur,choice pls_integer) is
--因为是弱类型,不能使用p_emp_cursor%notfound
--必须指定具体类型
v_emp_cur emp%rowtype;
v_dept_cur dept%rowtype;
begin
if choice=1 then
loop
fetch p_emp_cursor into v_emp_cur;
exit when p_emp_cursor%notfound;
dbms_output.put_line('弱类型-'||v_emp_cur.ename);
end loop;
else
loop
fetch p_emp_cursor into v_dept_cur;
exit when p_emp_cursor%notfound;
dbms_output.put_line('弱类型-'||v_dept_cur.dname);
end loop;
end if;
end;
--使用系统的弱类型
procedure c_get_info_weak2(p_emp_cursor sys_refcursor,choice pls_integer) is
--因为是弱类型,不能使用p_emp_cursor%notfound
--必须指定具体类型
v_emp_cur emp%rowtype;
v_dept_cur dept%rowtype;
begin
if choice=1 then
loop
fetch p_emp_cursor into v_emp_cur;
exit when p_emp_cursor%notfound;
dbms_output.put_line('弱类型-'||v_emp_cur.ename);
end loop;
else
loop
fetch p_emp_cursor into v_dept_cur;
exit when p_emp_cursor%notfound;
dbms_output.put_line('弱类型-'||v_dept_cur.dname);
end loop;
end if;
end;
begin
--强类型
open v_cur for
select * from emp where rownum<5;
c_get_info(v_cur);
--在oracle 11gR2中,支持多次打开同一个游标
open v_cur for
select * from emp where rownum<5;
c_get_info(v_cur);
close v_cur;
dbms_output.put_line('-------------------------');
--弱类型1
open v_cur2 for
select * from emp where rownum<5;
c_get_info_weak1(v_cur2,1);
open v_cur2 for
select * from dept where rownum<5;
c_get_info_weak1(v_cur2,2);
close v_cur2;
dbms_output.put_line('-------------------------');
--弱类型2
open v_cur3 for
select * from emp where rownum<5;
c_get_info_weak2(v_cur3,1);
open v_cur3 for
select * from dept where rownum<5;
c_get_info_weak2(v_cur3,2);
close v_cur3;
end;
/
例4:支持批量导入
--动态游标与bulk collect into
declare
v_cur sys_refcursor;
type c_dept_tb is table of dept%rowtype;
v_dept_tab c_dept_tb:=c_dept_tb();
begin
open v_cur for
select * from dept;
fetch v_cur bulk collect into v_dept_tab;
for x in 1 .. v_dept_tab.count loop
dbms_output.put_line(v_dept_tab(x).dname);
end loop;
close v_cur;
end;
/
O(∩_∩)O~~~