在Oracle中,游標(biāo)是一種機(jī)制,是通過(guò)關(guān)鍵字CURSOR的來(lái)定義一組Oracle查詢出來(lái)的數(shù)據(jù)集,可以把查詢的數(shù)據(jù)集存儲(chǔ)在內(nèi)存當(dāng)中,然后通過(guò)游標(biāo)指向其中一條記錄,通過(guò)循環(huán)游標(biāo)達(dá)到循環(huán)數(shù)據(jù)集的目的。
本教程操作環(huán)境:Windows7系統(tǒng)、Oracle 11g版、Dell G3電腦。
在Oracle中,游標(biāo)(Cursors)是一種機(jī)制,可以通過(guò)該機(jī)制將名稱分配給SELECT語(yǔ)句并處理該SQL語(yǔ)句中的信息。
Oracle游標(biāo)是通過(guò)關(guān)鍵字CURSOR的來(lái)定義一組Oracle查詢出來(lái)的數(shù)據(jù)集,類似數(shù)組一樣,把查詢的數(shù)據(jù)集存儲(chǔ)在內(nèi)存當(dāng)中,然后通過(guò)游標(biāo)指向其中一條記錄,通過(guò)循環(huán)游標(biāo)達(dá)到循環(huán)數(shù)據(jù)集的目的。
游標(biāo)有什么作用?
①指定結(jié)果集中特定行的位置。
②基于當(dāng)前的結(jié)果集位置檢索一行或連續(xù)的幾行。
③在結(jié)果集的當(dāng)前位置修改行中的數(shù)據(jù)。
④對(duì)其他用戶所做的數(shù)據(jù)更改定義不同的敏感性級(jí)別。
⑤可以以編程的方式訪問(wèn)數(shù)據(jù)庫(kù)。
Oracle游標(biāo)的類型?
1、靜態(tài)游標(biāo):結(jié)果集已經(jīng)確實(shí)(靜態(tài)定義)的游標(biāo)。分為隱式和顯示游標(biāo)
-
隱式游標(biāo):所有DML語(yǔ)句為隱式游標(biāo),通過(guò)隱式游標(biāo)屬性可以獲取SQL語(yǔ)句信息。
-
顯示游標(biāo):用戶顯示聲明的游標(biāo),即指定結(jié)果集。當(dāng)查詢返回結(jié)果超過(guò)一行時(shí),就需要一個(gè)顯式游標(biāo)。
2、REF游標(biāo):動(dòng)態(tài)關(guān)聯(lián)結(jié)果集的臨時(shí)對(duì)象。
Oracle游標(biāo)的狀態(tài)有哪些,怎么使用游標(biāo)屬性?
①游標(biāo)的狀態(tài)是通過(guò)屬性來(lái)表示。
-
%Found :Fetch語(yǔ)句(獲取記錄)執(zhí)行情況True or False。
-
%NotFound : 最后一條記錄是否提取出True or False。
-
%ISOpen : 游標(biāo)是否打開True or False。
-
%RowCount :游標(biāo)當(dāng)前提取的行數(shù) 。
②使用游標(biāo)的屬性。
例子:
/* conn scott/tiger */ Begin Update emp Set SAL = SAL + 0.1 Where JOB = 'CLERK'; If SQL%Found Then DBMS_OUTPUT.PUT_LINE('已經(jīng)更新!'); Else DBMS_OUTPUT.PUT_LINE('更新失??!'); End If; End;
如何使用顯示游標(biāo),?如何遍歷循環(huán)游標(biāo)?
1、使用顯示游標(biāo)
-
聲明游標(biāo):劃分存儲(chǔ)區(qū)域,注意此時(shí)并沒有執(zhí)行Select 語(yǔ)句。
CURSOR 游標(biāo)名( 參數(shù) 列表) [返回值類型] IS Select 語(yǔ)句;
-
打開游標(biāo):執(zhí)行Select 語(yǔ)句,獲得結(jié)果集存儲(chǔ)到游標(biāo)中,此時(shí)游標(biāo)指向結(jié)果集頭, 而不是第一條記錄。
Open 游標(biāo)名( 參數(shù) 列表);
-
獲取記錄:移動(dòng)游標(biāo)取一條記錄
Fetch 游標(biāo)名InTo 臨時(shí)記錄或?qū)傩灶愋妥兞浚?/pre>
-
關(guān)閉游標(biāo):將游標(biāo)放入緩沖池中,沒有完全釋放資源。可重新打開。
Close 游標(biāo)名;
2、遍歷循環(huán)游標(biāo)
-
For 循環(huán)游標(biāo)
循環(huán)游標(biāo)隱式打開游標(biāo),自動(dòng)滾動(dòng)獲取一條記錄,并自動(dòng)創(chuàng)建臨時(shí)記錄類型變量存儲(chǔ)記錄。處理完后自動(dòng)關(guān)閉游標(biāo)。
For 變量名 In 游標(biāo)名 Loop 數(shù)據(jù)處理語(yǔ)句; End Loop;
-
Loop循環(huán)游標(biāo)
。。。 Loop Fatch 游標(biāo)名InTo 臨時(shí)記錄或?qū)傩灶愋妥兞浚? Exit When 游標(biāo)名%NotFound; End Loop; 。。。
例子1:
/* conn scott/tiger */ Declare Cursor myCur is select empno,ename,sal from emp; vna varchar2(10); vno number(4); vsal number(7,2); Begin open myCur; fetch myCur into vno,vna,vsal; dbms_output.put_line(vno||' '||vna||' '||vsal); close myCur; End; /
例子2:使用loop遍歷游標(biāo)。
/* conn scott/tiger */ Declare Cursor myCur is select ename,job,sal,empno from emp; varE myCur%rowType; Begin if myCur%isopen = false then open myCur; dbms_output.put_line('Opening...'); end if; loop fetch myCur into varE; exit when myCur%notfound; dbms_output.put_line(myCur%rowCount||' '||vare.empno||' '||vare.ename||' '||vare.sal); end loop; if myCur%isopen then Close myCur; dbms_output.put_line('Closing...'); end if; End; /
例子3:使用For循環(huán)遍歷游標(biāo),
/* conn scott/tiger */ Declare Cursor myCur is select * from emp; Begin for varA in myCur loop dbms_output.put_line(myCur%rowCount||' '||varA.empno||' '||varA.ename||' '||varA.sal); end loop; End; /
怎樣更新和刪除顯示游標(biāo)中的記錄?
①UPDATE或DELETE語(yǔ)句中的WHERE CURRENT OF子串專門處理要執(zhí)行UPDATE或DELETE操作的表中取出的最近的數(shù)據(jù)。
要使用這個(gè)方法,在聲明游標(biāo)時(shí)必須使用FOR UPDATE子串,當(dāng)對(duì)話使用FOR UPDATE子串打開一個(gè)游標(biāo)時(shí),
所有返回集中的數(shù)據(jù)行都將處于行級(jí)(ROW-LEVEL)獨(dú)占式鎖定,其他對(duì)象只能查詢這些數(shù)據(jù)行,
不能進(jìn)行UPDATE、DELETE或SELECT…FOR UPDATE操作。
在多表查詢中,使用OF子句來(lái)鎖定特定的表,如果忽略了OF子句,那么所有表中選擇的數(shù)據(jù)行都將被鎖定。
如果這些數(shù)據(jù)行已經(jīng)被其他會(huì)話鎖定,那么正常情況下ORACLE將等待,直到數(shù)據(jù)行解鎖。
②使用更新或刪除:
⑴聲明更新或刪除顯示游標(biāo):
Cursor 游標(biāo)名IS SELECT 語(yǔ)句 For Update [ Of 更新列列名]; Cursor 游標(biāo)名IS SELECT 語(yǔ)句 For Delete [ Of 更新列列名];
⑵使用顯示游標(biāo)當(dāng)前記錄來(lái)更新或刪除:
Update 表名 SET 更新語(yǔ)句 Where Current Of 游標(biāo)名; Delete From 表名 Where Current Of 游標(biāo)名;
例子1:更新顯示游標(biāo)記錄
/*conn scott/tiger*/ Declare Cursor myCur is select job from emp for update; vjob empa.job%type; rsal empa.sal%type; Begin open myCur; loop fetch myCur into vjob; exit when myCur%notFound; case (vjob) when 'ANALYST' then rsal := 0.1; when 'CLERK' then rsal := 0.2; when 'MANAGER' then rsal := 0.3; else rsal := 0.5; end case; update emp set sal = sal + rsal where current of myCur; end loop; End; /
例子2:刪除顯示游標(biāo)記錄
/*conn scott/tiger Crate table empa Select * from scott.emp; */ Declare Cursor MyCursor Select JOB From empa For Update; vSal emp.Sal%TYPE; Begin Loop Fetch MyCursor InTo vSal; Exit When MyCursor%NotFound; If vSal < 800 Then Delete From empa Where Cursor Of MyCursor; End If; End Loop; End;/
什么是帶參數(shù)的顯示游標(biāo)?
1、與過(guò)程和函數(shù)相似,可以將參數(shù)傳遞給游標(biāo)并在查詢中使用。
參數(shù)只定義數(shù)據(jù)類型,沒有大小(所有Oracle中的形參只定義數(shù)據(jù)類型,不指定大小)。
與過(guò)程不同的是,游標(biāo)只能接受傳遞的值,而不能返回值。
可以給參數(shù)設(shè)定一個(gè)缺省值,當(dāng)沒有參數(shù)值傳遞給游標(biāo)時(shí),就使用缺省值。
游標(biāo)中定義的參數(shù)只是一個(gè)占位符,在別處引用該參數(shù)不一定可靠。
2、使用帶參數(shù)的顯示游標(biāo)
-
聲明帶參數(shù)的顯示游標(biāo):
CURSOR 游標(biāo)名 [(parameter[,parameter],...)] IS Select語(yǔ)句;
參數(shù)形式:
1,參數(shù)名 數(shù)據(jù)類型
2,參數(shù)名 數(shù)據(jù)類型 DEFAULT 默認(rèn)值
例子:
/*conn scott/tiger Crate table empa Select * from scott.emp; */ Declare Cursor MyCursor(pSal Number Default 800) Select JOB From empa Where SAL > pSal ; varA MyCursor%ROWTYPE; Begin Loop Fetch MyCursor InTo varA; Exit When MyCursor%NotFound; DBMS_OUTPUT.PUT_LINE(MyCursor%RowCount||' '||varA.empno||' '||varA.ename||' '||varA.sal); End Loop; End;/
推薦教程:《Oracle教程》