在Oracle中,游標是一種機制,是通過關鍵字CURSOR的來定義一組Oracle查詢出來的數據集,可以把查詢的數據集存儲在內存當中,然后通過游標指向其中一條記錄,通過循環游標達到循環數據集的目的。

本教程操作環境:Windows7系統、Oracle 11g版、Dell G3電腦。
在Oracle中,游標(Cursors)是一種機制,可以通過該機制將名稱分配給SELECT語句并處理該SQL語句中的信息。
Oracle游標是通過關鍵字CURSOR的來定義一組Oracle查詢出來的數據集,類似數組一樣,把查詢的數據集存儲在內存當中,然后通過游標指向其中一條記錄,通過循環游標達到循環數據集的目的。
游標有什么作用?
①指定結果集中特定行的位置。
②基于當前的結果集位置檢索一行或連續的幾行。
③在結果集的當前位置修改行中的數據。
④對其他用戶所做的數據更改定義不同的敏感性級別。
⑤可以以編程的方式訪問數據庫。
Oracle游標的類型?
1、靜態游標:結果集已經確實(靜態定義)的游標。分為隱式和顯示游標
-
隱式游標:所有DML語句為隱式游標,通過隱式游標屬性可以獲取SQL語句信息。
-
顯示游標:用戶顯示聲明的游標,即指定結果集。當查詢返回結果超過一行時,就需要一個顯式游標。
2、REF游標:動態關聯結果集的臨時對象。
Oracle游標的狀態有哪些,怎么使用游標屬性?
①游標的狀態是通過屬性來表示。
-
%Found :Fetch語句(獲取記錄)執行情況True or False。
-
%NotFound : 最后一條記錄是否提取出True or False。
-
%ISOpen : 游標是否打開True or False。
-
%RowCount :游標當前提取的行數 。
②使用游標的屬性。
例子:
/* conn scott/tiger */ Begin Update emp Set SAL = SAL + 0.1 Where JOB = 'CLERK'; If SQL%Found Then DBMS_OUTPUT.PUT_LINE('已經更新!'); Else DBMS_OUTPUT.PUT_LINE('更新失敗!'); End If; End;
如何使用顯示游標,?如何遍歷循環游標?
1、使用顯示游標
-
聲明游標:劃分存儲區域,注意此時并沒有執行Select 語句。
CURSOR 游標名( 參數 列表) [返回值類型] IS Select 語句;
-
打開游標:執行Select 語句,獲得結果集存儲到游標中,此時游標指向結果集頭, 而不是第一條記錄。
Open 游標名( 參數 列表);
-
獲取記錄:移動游標取一條記錄
Fetch 游標名InTo 臨時記錄或屬性類型變量;
-
關閉游標:將游標放入緩沖池中,沒有完全釋放資源。可重新打開。
Close 游標名;
2、遍歷循環游標
-
For 循環游標
循環游標隱式打開游標,自動滾動獲取一條記錄,并自動創建臨時記錄類型變量存儲記錄。處理完后自動關閉游標。
For 變量名 In 游標名 Loop 數據處理語句; End Loop;
-
Loop循環游標
。。。 Loop Fatch 游標名InTo 臨時記錄或屬性類型變量; Exit When 游標名%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遍歷游標。
/* 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循環遍歷游標,
/* 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; /
怎樣更新和刪除顯示游標中的記錄?
①UPDATE或DELETE語句中的WHERE CURRENT OF子串專門處理要執行UPDATE或DELETE操作的表中取出的最近的數據。
要使用這個方法,在聲明游標時必須使用FOR UPDATE子串,當對話使用FOR UPDATE子串打開一個游標時,
所有返回集中的數據行都將處于行級(ROW-LEVEL)獨占式鎖定,其他對象只能查詢這些數據行,
不能進行UPDATE、DELETE或SELECT…FOR UPDATE操作。
在多表查詢中,使用OF子句來鎖定特定的表,如果忽略了OF子句,那么所有表中選擇的數據行都將被鎖定。
如果這些數據行已經被其他會話鎖定,那么正常情況下ORACLE將等待,直到數據行解鎖。
②使用更新或刪除:
⑴聲明更新或刪除顯示游標:
Cursor 游標名IS SELECT 語句 For Update [ Of 更新列列名]; Cursor 游標名IS SELECT 語句 For Delete [ Of 更新列列名];
⑵使用顯示游標當前記錄來更新或刪除:
Update 表名 SET 更新語句 Where Current Of 游標名; Delete From 表名 Where Current Of 游標名;
例子1:更新顯示游標記錄
/*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:刪除顯示游標記錄
/*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;/
什么是帶參數的顯示游標?
1、與過程和函數相似,可以將參數傳遞給游標并在查詢中使用。
參數只定義數據類型,沒有大小(所有Oracle中的形參只定義數據類型,不指定大小)。
與過程不同的是,游標只能接受傳遞的值,而不能返回值。
可以給參數設定一個缺省值,當沒有參數值傳遞給游標時,就使用缺省值。
游標中定義的參數只是一個占位符,在別處引用該參數不一定可靠。
2、使用帶參數的顯示游標
-
聲明帶參數的顯示游標:
CURSOR 游標名 [(parameter[,parameter],...)] IS Select語句;
參數形式:
1,參數名 數據類型
2,參數名 數據類型 DEFAULT 默認值
例子:
/*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教程》
站長資訊網