cursor分为三种,一是直接声明为cursor变量,二是首先声明类型再声明变量,三是声明为sys_refcursor。
(1)直接声明
declare
cursoremp_curisselect*fromemp;
emp_record emp%rowtype;
begin
openemp_cur;
loop
fetchemp_curintoemp_record;
exitwhenemp_cur%notfound;
dbms_output.put_line('name is:'||
emp_record.ename ||' and sal is:'|| emp_record.sal);
endloop;
closeemp_cur;
end;
/
(2)ref cursor:分为强类型(有return子句的)和弱类型,强类型在使用时,其返回类型必须和return中的类型一致,否则报错,而弱类型可以随意打开任何类型。
例如:
强类型
declare
typeemp_cur_typeisrefcursorreturnemp%rowtype;
emp_cur emp_cur_type;
emp_record emp%rowtype;
begin
openemp_curforselect*fromemp;
loop
fetchemp_curintoemp_record;
exitwhenemp_cur%notfound;
dbms_output.put_line('name is:'||emp_record.ename ||' and sal is:'||
emp_record.sal);
endloop;
closeemp_cur;
--open emp_cur for select * from
dept;错误的,类型不一致。
--close emp_cur;
end;
/
弱类型:
declare
typeemp_cur_typeisrefcursor;
emp_cur emp_cur_type;
emp_record emp%rowtype;
dept_record dept%rowtype;
begin
openemp_curforselect*fromemp;
loop
fetchemp_curintoemp_record;
exitwhenemp_cur%notfound;
dbms_output.put_line('name is:'||
emp_record.ename ||' and sal is:'|| emp_record.sal);
endloop;
closeemp_cur;
openemp_curforselect*fromdept;--可再次打开,不同类型的
loop
fetchemp_curintodept_record;
exitwhenemp_cur%notfound;
dbms_output.put_line('dname is:'||
dept_record.dname);
endloop;
closeemp_cur;
end;
/
(3)sys_refcursor:可多次打开,直接声明此类型的变量,不用先定义类型再声明变量。
declare
emp_cursys_refcursor;
emp_record emp%rowtype;
dept_record dept%rowtype;
begin
openemp_curforselect*fromemp;
loop
fetchemp_curintoemp_record;
exitwhenemp_cur%notfound;
dbms_output.put_line('name is:'||
emp_record.ename ||' and sal is:'|| emp_record.sal);
endloop;
closeemp_cur;
openemp_curforselect*fromdept;--可再次打开,不同类型的
loop
fetchemp_curintodept_record;
exitwhenemp_cur%notfound;
dbms_output.put_line('dname is:'||
dept_record.dname);
endloop;
closeemp_cur;
end;
/
其他总结:
1、游标可以用for循环,但只限于cursor cur_var is……这种类型,用在其他的里面都是错误的;for本身就包含了打开、关闭游标,此时再显示打开关闭都是错误的。
declare
cursoremp_curisselect*fromemp;
begin
--open emp_cur;是错误的,因为for本身就包含了打开、关闭
foremp_recordinemp_cur
loop
dbms_output.put_line('name is:'||emp_record.ename ||' and sal is:'||
emp_record.sal);
endloop;
--close emp_cur;是错误的,for本身包含了关闭。
end;
--是不是表示:ref cursor变量不支持for打开并循环?
declare
typeemp_cur_typeisrefcursorreturnemp%rowtype;
emp_cur emp_cur_type;
begin
openemp_curforselect*fromemp;--怎么都是错,for已经打开了。
foremp_recordinemp_cur--不管前面有没有打开语句,for都不承认这种类型
loop
dbms_output.put_line('name is:'||emp_record.ename ||' and sal is:'||
emp_record.sal);
endloop;
end;
2、游标可以带参数
DECLARE
CURSORc1 (jobVARCHAR2, max_wageNUMBER)IS
SELECT*FROMemployeesWHEREjob_id = jobANDsalary >
max_wage;
BEGIN
FORpersonINc1('CLERK',3000)
LOOP
DBMS_OUTPUT.PUT_LINE('Name = '||
person.last_name ||', salary = '||
person.salary ||', Job Id = '|| person.job_id );
ENDLOOP;
END;
3、bulk collect批量赋值
declare
typeemp_cur_typeisrefcursor;
emp_cur emp_cur_type;
typename_lististableofemp.ename%type;
typesal_lististableofemp.sal%type;
names name_list;
sals sal_list;
begin
openemp_curforselectename,salfromemp;
fetchemp_curbulkcollectintonames,sals;
closeemp_cur;
foriinnames.first .. names.last
loop
dbms_output.put_line('name is:'||names(i)||' and sal is:'||sals(i));
endloop;
end;
/
4、cursor变量的位置
CREATEPACKAGEemp_dataAS
TYPEEmpCurTypISREFCURSORRETURNemployees%ROWTYPE;
-- emp_cv EmpCurTyp; -- not allowed
PROCEDUREopen_emp_cv;
ENDemp_data;
/
CREATEPACKAGEBODYemp_dataAS
-- emp_cv EmpCurTyp; -- not allowed
PROCEDUREopen_emp_cvIS
emp_cv EmpCurTyp;-- this is legal
BEGIN
OPENemp_cvFORSELECT*FROMemployees;
ENDopen_emp_cv;
ENDemp_data;
/
5、嵌套cursor
打开父cursor时,子cursor隐含打开;当
语法格式:cursor(subquery)
Anestedcursorisimplicitly openedwhenthecontainingrowisfetchedfromtheparentcursor.
Thenestedcursorisclosedonlywhen:
Thenestedcursorisexplicitly closedbytheuser
Theparentcursorisreexecuted
Theparentcursorisclosed
Theparentcursoriscanceled
示例;declare
typeemp_cur_typeisrefcursor;
typedept_cur_typeisrefcursor;
v_ename emp.ename%type;
v_dname dept.dname%type;
emp_cur emp_cur_type;
dept_cur dept_cur_type;
begin
opendept_curfor
selectd.dname,
cursor(selecte.enamefromemp ewheree.deptno=d.deptno )emps
fromdept d;
loop
fetchdept_curintov_dname,emp_cur;
exitwhendept_cur%notfound;
dbms_output.put_line('dname is : '||v_dname);
loop
fetchemp_curintov_ename;
exitwhenemp_cur%notfound;
dbms_output.put_line('--ename is : '||v_ename);
endloop;
endloop;
closedept_cur;
end;
225

被折叠的 条评论
为什么被折叠?



