游標(biāo)
:
用來(lái)查詢(xún)數(shù)據(jù)庫(kù),獲取記錄集合(結(jié)果集)的指針,可以讓開(kāi)發(fā)者一次訪問(wèn)一行結(jié)果集,在每條結(jié)果集上作操作。
分類(lèi)
:
靜態(tài)游標(biāo):
分為顯式游標(biāo)和隱式游標(biāo)。
REF游標(biāo):
是一種引用類(lèi)型,類(lèi)似于指針。
?
顯式游標(biāo)
:
?CURSOR?游標(biāo)名?(?參數(shù)?)?[返回值類(lèi)型]?IS
??Select?語(yǔ)句
生命周期:
1.打開(kāi)游標(biāo)(OPEN)
解析,綁定。。。不會(huì)從數(shù)據(jù)庫(kù)檢索數(shù)據(jù)
2.從游標(biāo)中獲取記錄(FETCH?INTO)
執(zhí)行查詢(xún),返回結(jié)果集。通常定義局域變量作為從游標(biāo)獲取數(shù)據(jù)的緩沖區(qū)。
3.關(guān)閉游標(biāo)(CLOSE)
完成游標(biāo)處理,用戶(hù)不能從游標(biāo)中獲取行。還可以重新打開(kāi)。
選項(xiàng):參數(shù)和返回類(lèi)型
set?serveroutput?on
declare
?cursor?emp_cur?(?p_deptid?in?number)?is?
select?*?from?employees?where?department_id?=?p_deptid;
l_emp?employees%rowtype;
begin
?dbms_output.put_line('Getting?employees?from?department?30');
open?emp_cur(30);
?loop
??fetch?emp_cur?into?l_emp;
??exit?when?emp_cur%notfound;
??dbms_output.put_line('Employee?id?'||?l_emp.employee_id?||?'?is?');
??dbms_output.put_line(l_emp.first_name?||?'?'?||?l_emp.last_name);
?end?loop;
?close?emp_cur;
?dbms_output.put_line('Getting?employees?from?department?90');
open?emp_cur(90);
?loop
??fetch?emp_cur?into?l_emp;
??exit?when?emp_cur%notfound;
??dbms_output.put_line('Employee?id?'||?l_emp.employee_id?||?'?is?');
??dbms_output.put_line(l_emp.first_name?||?'?'?||?l_emp.last_name);
?end?loop;
?close?emp_cur;
end;
/
?
隱式游標(biāo)
:
不用明確建立游標(biāo)變量,分兩種:
1.在PL/SQL中使用DML語(yǔ)言,使用ORACLE提供的名為SQL的隱示游標(biāo)
2.CURSOR?FOR?LOOP,用于for?loop?語(yǔ)句
1舉例:
declare
begin
?update?departments?set?department_name=department_name;
?--where?1=2;
?
?dbms_output.put_line('update?'||?sql%rowcount?||'?records');
end;
/
2舉例:
declare
begin
?for?my_dept_rec?in?(?select?department_name,?department_id?from?departments)
?loop
??dbms_output.put_line(my_dept_rec.department_id?||?'?:?'?||?my_dept_rec.department_name);
?end?loop;
end;
/
3舉例:
單獨(dú)select?
declare
?l_empno?emp.EMPLOYEE_ID%type;
--?l_ename?emp.ename%type;
begin
?select?EMPLOYEE_ID????
??into?l_empno
?from?emp;
?--where?rownum?=1;
?dbms_output.put_line(l_empno);
end;
/
使用INTO獲取值,只能返回一行。
?
游標(biāo)屬性
:
%FOUND:變量最后從游標(biāo)中獲取記錄的時(shí)候,在結(jié)果集中找到了記錄。
%NOTFOUND:變量最后從游標(biāo)中獲取記錄的時(shí)候,在結(jié)果集中沒(méi)有找到記錄。
%ROWCOUNT:當(dāng)前時(shí)刻已經(jīng)從游標(biāo)中獲取的記錄數(shù)量。
%ISOPEN:是否打開(kāi)。
Declare
?Cursor?emps?is
?Select?*?from?employees?where?rownum<6?order?by?1;
?
?Emp?employees%rowtype;
?Row?number?:=1;
Begin
?Open?emps;
?Fetch?emps?into?emp;
?
?Loop
??If?emps%found?then
???Dbms_output.put_line('Looping?over?record?'||row||?'?of?'?||?emps%rowcount);
???Fetch?emps?into?emp;
???Row?:=?row?+?1;
??Elsif?emps%notfound?then
???Exit;??---exit?loop,?not?IF
??End?if;
?End?loop;
?
?If?emps%isopen?then
??Close?emps;
?End?if;
End;
/
?
顯式和隱式游標(biāo)的區(qū)別
:
盡量使用隱式游標(biāo),避免編寫(xiě)附加的游標(biāo)控制代碼(聲明,打開(kāi),獲取,關(guān)閉),也不需要聲明變量來(lái)保存從游標(biāo)中獲取的數(shù)據(jù)。
?
REF?CURSOR游標(biāo)
:
動(dòng)態(tài)游標(biāo),在運(yùn)行的時(shí)候才能確定游標(biāo)使用的查詢(xún)。分類(lèi):
強(qiáng)類(lèi)型(限制)REF?CURSOR,規(guī)定返回類(lèi)型?
弱類(lèi)型(非限制)REF?CURSOR,不規(guī)定返回類(lèi)型,可以獲取任何結(jié)果集。
TYPE?ref_cursor_name?IS?REF?CURSOR?[RETURN?return_type]
Declare
?Type?refcur_t?is?ref?cursor;
?
?Type?emp_refcur_t?is?ref?cursor?return?employee%rowtype;
Begin
?Null;
End;
/
強(qiáng)類(lèi)型舉例:
declare
?--聲明記錄類(lèi)型
?type?emp_job_rec?is?record(
??employee_id?number,
??employee_name?varchar2(50),
??job_title?varchar2(30)
?);
?--聲明REF?CURSOR,返回值為該記錄類(lèi)型
?type?emp_job_refcur_type?is?ref?cursor
??return?emp_job_rec;
?--定義REF?CURSOR游標(biāo)的變量
?emp_refcur?emp_job_refcur_type;
?emp_job?emp_job_rec;
begin
?open?emp_refcur?for
??select?e.employee_id,
????e.first_name?||?'?'?||e.last_name?"employee_name",
????j.job_title
??from?employees?e,?jobs?j
??where?e.job_id?=?j.job_id?and?rownum?<?11?order?by?1;
?fetch?emp_refcur?into?emp_job;
?while?emp_refcur%found?loop
??dbms_output.put_line(emp_job.employee_name?||?'''s?job?is?');
??dbms_output.put_line(emp_job.job_title);
??fetch?emp_refcur?into?emp_job;
?end?loop;
end;