游標(biāo)用于處理查詢結(jié)果集中的數(shù)據(jù)
Oracle中提供了兩種游標(biāo)類型,它們是:
靜態(tài)游標(biāo):靜態(tài)游標(biāo)是在編譯時知道Select語句的游標(biāo)。靜態(tài)游標(biāo)又分為兩種類型,隱式游標(biāo)和顯式游標(biāo)。
REF游標(biāo):很多時候用戶需要為游標(biāo)使用的查詢直到運行的時候才能確定,可以使用REF游標(biāo)(引用游標(biāo))和游標(biāo)變量滿足這個要求。為了使用引用游標(biāo),必須聲明游標(biāo)變量。有兩種類型的REF游標(biāo),強(qiáng)類型REF游標(biāo)和弱類型REF游標(biāo)。
1、隱式游標(biāo):PL/SQL為所有SQL數(shù)據(jù)操縱語句(包括返回一行的Select)隱式聲明游標(biāo)。用戶不能直接命名和控制此類游標(biāo)。隱式游標(biāo)名為SQL。
隱式游標(biāo)屬性:
(1)、%FOUND只有在DML語句影響一行或多行時,%FOUND屬性才返回TRUE。
示例1:如果有行被更新,SQL%FOUND就返回真并打印相應(yīng)信息。
begin
updateempsetsal=sal+8whereempno=7900;
ifsql%foundthen
dbms_output.put_line('表已更新');
else
dbms_output.put_line('編號未找到');
endif;
end;
(2)、%NOTFOUND此屬性與%FOUND屬性的作用正好相反。如果DML語句沒有影響任何行,則%NOTFOUND屬性返回TRUE。
(3)、%ROWCOUNT此屬性返回DML語句影響的行數(shù)。如果DML語句沒有影響任何行,則%ROWCOUNT屬性將返回0。
示例2:使用%ROWCOUNT屬性。
begin
updateempsetsal=sal+8whereempno=7900;
ifsql%foundthen
dbms_output.put_line('表已更新,更新了'||SQL%ROWCOUNT||'行');
else
dbms_output.put_line('編號未找到');
endif;
end;
(4)、%ISOPEN此屬性返回游標(biāo)是否已打開的值。隱式游標(biāo)的%ISOPEN屬性始終為FALSE。
2、顯式游標(biāo)
使用顯式游標(biāo)的4個步驟是:
(1)、聲明游標(biāo)。
(2)、打開游標(biāo)。
(3)、從游標(biāo)中獲取記錄
(4)、關(guān)閉游標(biāo)
聲明顯式游標(biāo)語法:
CURSORcursor_name[(parameter[,parameter]...)]
[RETURNreturn_type]ISselect_statement;
其中:cursor_name指游標(biāo)的名稱。
parameter用于為游標(biāo)指定輸入?yún)?shù)。
return_type定義游標(biāo)提取的行的類型。
select_statement指游標(biāo)定義的查詢語句。
打開游標(biāo)語法:
OPENcursor_name[(parameters)];
從游標(biāo)中獲取記錄語法:
FETCHcursor_nameINTOvariables;
其中:cursor_name指游標(biāo)的名稱。
variables是變量名。
關(guān)閉游標(biāo)語法:
CLOSEcursor_name;
顯式游標(biāo)的屬性如下:
(1)、%FOUND如果執(zhí)行后一條FETCH語句成功返回行,則%FOUND的值為TRUE。
(2)、%NOTFOUND如果執(zhí)行后一條FETCH語句未能提取行時,則%NOTFOUND的值為TRUE。
(3)、%ROWCOUNT返回到目前為止游標(biāo)提取的行數(shù)。在第一次獲取之前,%ROWCOUNT為零。當(dāng)FETCH語句返回一行時,則該數(shù)加1。
(4)、%ISOPEN如果游標(biāo)已經(jīng)打開,則返回TRUE,否則返回FALSE。
我們來一起看一個稍微復(fù)雜的例子
setserveroutputon
declare
cursorcur_deptisselect*fromdeptorderbydeptno;--定義游標(biāo)
cursorcur_emp(mydeptnoinnumber)is
selectename,salfromempwheredeptno=mydeptno;
dept_recdept%rowtype;--聲明記錄類型變量
emp_recemp%rowtype;
mydeptnodept.deptno%type;
mydeptnamedept.dname%type;
myempnoemp.empno%type;
myenameemp.ename%type;
mysalemp.sal%type;
mytotalsalemp.sal%type;
begin
opencur_dept;--打開游標(biāo)
loop
fetchcur_deptintodept_rec;--提取游標(biāo)中的數(shù)據(jù)到記錄類型中
exitwhencur_dept%notfound;
dbms_output.put_line('departnois:'||dept_rec.deptno);
opencur_emp(dept_rec.deptno);
loop
fetchcur_empintomyename,mysal;
exitwhencur_emp%notfound;
dbms_output.put_line('employeenameis:'||myename);
dbms_output.put_line('salaryis:'||mysal);
--mytotalsal:=mytotalsal+mysal;
endloop;
closecur_emp;--關(guān)閉游標(biāo)
--dbms_output.put_line('emploueesalaryis:'||mytotalsal);
endloop;
closecur_dept;
end;
三ref游標(biāo)
REF游標(biāo)和游標(biāo)變量用于處理運行時動態(tài)執(zhí)行的SQL查詢
創(chuàng)建游標(biāo)變量需要兩個步驟:
聲明REF游標(biāo)類型
聲明REF游標(biāo)類型的變量
注意:不能賦予游標(biāo)具體的sql語句
看一個例子
setserveroutputon
declare
typeemp_curisrefcursor;--聲明REF游標(biāo)類型
emp_cur_objemp_cur;--聲明REF游標(biāo)類型的變量
emp_recemp%rowtype;
dept_recdept%rowtype;
v_salemp.sal%type;
begin
v_sal:='&inputsal';
ifv_sal>3000then
openemp_cur_objforselect*fromemp;--給游標(biāo)賦予動態(tài)的sql語句
loop
fetchemp_cur_objintoemp_rec;
exitwhenemp_cur_obj%notfound;
dbms_output.put_line('employeenameis'||emp_rec.ename);
endloop;
else
openemp_cur_objforselect*fromdept;--給游標(biāo)賦予動態(tài)的sql語句
loop
fetchemp_cur_objintodept_rec;
exitwhenemp_cur_obj%notfound;
dbms_output.put_line('部門:'||dept_rec.dname);
endloop;
dbms_output.put_line('工資小于3000只查看部門信息');
endif;
closeemp_cur_obj;
end;