(七)Oracle學習筆記—— 遊標
1.遊標簡介
遊標用來處理從數據庫中檢索的多行記錄(使用SELECT語句)。利用遊標,程序可以逐個地處理和遍歷一次檢索返回的整個記錄集。
為了處理SQL語句,Oracle將在內存中分配一個區域,這就是上下文區。這個區包含了已經處理完的行數、指向被分析語句的指針,整個區是查詢(select)語句返回的數據行集。遊標就是指向上下文區句柄或指針。
2.遊標使用
2.1 定義一個遊標
CURSOR cursor_name IS select_statement;
例如:把數據表中emp中部門號為20的員工定義為遊標:
CURSOR exce_emp is select* from scott.emp where deptno=20;
註意:在聲明遊標時,select_statement不能包含INTO子句。當使用顯示遊標時,INTO子句是FETCH語句的一部分。
2.2 為查詢打開遊標
打開遊標實際上是從數據表中讀取數據的過程,在這個過程中主要完成兩件事:
①把select查詢結果讀入內存工作區中。
②將遊標指針定位在第一條記錄。
OPEN cursor_name
2.3 取得結果放入PL/SQL變量中(利用fetch命令從遊標中提取數據)
FETCH命令首先將當前遊標指針所指的行讀出來並且置於相應的變量中,然後把遊標指針移到下一行。所以FETCH命令每一個執行的時候,只能提取一行或者部分的數據。
FETCH cursor_name INTO list_of_variables; --變量(變量名1,變量名2......) FETCH cursor_name INTO PL/SQL_record; --記錄型變量名
2.4 關閉遊標
CLOSE cursor_name
舉例:
declare cursor exce_emp is select * from emp where empno=6676; --定義遊標 var_exce_emp exce_emp%rowtype; --定義變量 beginopen exce_emp; --打開遊標 fetch exce_emp into var_exce_emp; --fetch提取數據 dbms_output.put_line(‘提取的數據為:員工的姓名:‘||var_exce_emp.ename||‘,員工的工作為:‘||var_exce_emp.job); close exce_emp; end;
3.遊標的屬性
針對2.3,如果遊標指針已經指到了遊標的末尾,那麽FETCH命令將讀不到數據了,所以有這樣一種機制,這種機制可以測出遊標是否已經指到了遊標的末尾。這種機制就是遊標的屬性。
遊標有四個屬性:%FOUND、%ISOPEN、%NOTFOUND、%ROWCOUNT。
3.1 %FOUND
該屬性用於測試在自己所在語句之前的最後一個FETCH命令是否提取到了數據。如果能夠提取到數據就返回true,否則返回false。但是如果一個遊標還沒有被打開就運用%FOUND,那麽將會產生INVALID_CURSOR異常。
declare cursor exce_emp is select empno,ename from emp where deptno=20; var_exce_emp exce_emp%rowtype; i int := 1; begin open exce_emp; loop fetch exce_emp into var_exce_emp; if exce_emp %found then --利用%found屬性檢測是否提取到了數據 dbms_output.put_line(‘第‘||to_char(i)||‘個員工的信息-------編號:‘||var_exce_emp.empno||‘員工姓名:‘||var_exce_emp.ename); i := i+1; else exit; end if; end loop; close exce_emp; end;
3.2 %ISOPEN
該屬性主要用於測試遊標是否已經打開。
declare cursor exce_emp is select empno,ename from emp; var_exce_emp exce_emp%rowtype; begin if not exce_emp%isopen then --檢測遊標是否已經打開 dbms_output.put_line(‘遊標沒有打開‘); open exce_emp; else dbms_output.put_line(‘遊標已經打開了‘); end if; end;
3.3 %NOTFOUND
fetch是否提到數據 沒有true 提到false。
3.4 %ROWCOUNT
已經取出的記錄的條數
當剛剛打開遊標時,%ROWCOUNT的值為0。每運行一次FETCH命令,%ROWCOUNT的值就會自增1。因此%ROWCOUNT的值可以看著是遊標中當前被讀取了的記錄的條數,即遊標循環中處理的當前行數。如果一個有遊標在打開之前調用%ROWCOUNT屬性,就會產生異常INVALID_CURSOR。
declare cursor exce_emp is empno,ename from emp where deptno=20; var_exce_emp exce_emp%rowtype; n int := 5; begin open exce_emp; loop fetch exce_emp into var_exce_emp; exit when exce_emp%notfound; dbms_output.put_line(‘員工號:‘||var_exce_emp.empno||‘,員工姓名:‘||var_exce_emp.ename); exit when exce_emp%rowcount=n; end loop; close exce_emp; end;
4.隱式遊標
【2.遊標使用】介紹的都是顯式遊標。Oracle還默認了一種遊標,這個遊標就是隱式遊標,隱式遊標是不需要打開和關閉的。其被定義為SQL。它同時也具有4個屬性。
declare tempdeptno := 20; counts int := 0; begin update emp set job=‘CLERK‘ where deptno = tempdeptno; if sql%found then counts := sql%rowcount; end if; dbms_output.put_line(‘對‘||to_char(counts)||‘行語句做了修改‘); end;
顯式遊標和隱式遊標的區別:
5.遊標的常見操作
5.1 FOR循環遊標 (常用的一種遊標)
--<1>定義遊標 --<2>定義遊標變量 --<3>使用for循環來使用這個遊標 --前向遊標 只能往一個方向走 --效率很高 declare --類型定義 cursor cc is select empno,ename,job,sal from emp where job = ‘MANAGER‘; --定義一個遊標變量 ccrec cc%rowtype; begin --for循環 for ccrec in cc loop dbms_output.put_line(ccrec.empno||‘-‘||ccrec.ename||‘-‘||ccrec.job||‘-‘||ccrec.sal); end loop; end;
5.2 FETCH遊標
--使用的時候 必須要明確的打開和關閉 declare --類型定義 cursor cc is select empno,ename,job,sal from emp where job = ‘MANAGER‘; --定義一個遊標變量 ccrec cc%rowtype; begin --打開遊標 open cc; --loop循環 loop --提取一行數據到ccrec中 fetch cc into ccrec; --判斷是否提取到值,沒取到值就退出 --取到值cc%notfound 是false --取不到值cc%notfound 是true exit when cc%notfound; dbms_output.put_line(ccrec.empno||‘-‘||ccrec.ename||‘-‘||ccrec.job||‘-‘||ccrec.sal); end loop; --關閉遊標 close cc; end;
5.3 參數遊標
--按部門編號的順序輸出部門經理的名字 declare --部門 cursor c1 is select deptno from dept; --參數遊標c2,定義參數的時候 --只能指定類型,不能指定長度 --參數只能出現在select語句=號的右側 cursor c2(no number,pjob varchar2) is select emp.* from emp where deptno = no and job=pjob; c1rec c1%rowtype; c2rec c2%rowtype; --定義變量的時候要指定長度 v_job varchar2(20); begin --部門 for c1rec in c1 loop --參數在遊標中使用 for c2rec in c2(c1rec.deptno,‘MANAGER‘) loop dbms_output.put_line(c1rec.deptno||‘-‘||c2rec.ename); end loop; end loop; end;
5.4 引用遊標 / 動態遊標
-- select語句是動態的 declare --定義一個類型(ref cursor)弱類型 type cur is ref cursor; --強類型(返回的結果集有要求) type cur1 is ref cursor return emp%rowtype; --定義一個ref cursor類型的變量 cura cur; c1rec emp%rowtype; c2rec dept%rowtype; begin DBMS_output.put_line(‘輸出員工‘) ; open cura for select * from emp; loop fetch cura into c1rec; exit when cura%notfound; DBMS_output.put_line(c1rec.ename) ; end loop ; DBMS_output.put_line(‘輸出部門‘) ; open cura for select * from dept; loop fetch cura into c2rec; exit when cura%notfound; DBMS_output.put_line(c2rec.dname) ; end loop; close cura; end;
(七)Oracle學習筆記—— 遊標