PL/SQL遊標

遊標的屬性簡介:
遊標分爲顯示遊標和隱式遊標.
① %fFOUND	記錄獲取成功返回true,否則返回false
② %NOTFOUND		記錄獲取失敗返回true,否則返回false
③ %ROWCOUNT	返回已經從遊標中獲取的記錄數
④ %ISOPEN		如果遊標式打開的的,返回true,否則返回false(隱式遊標是oracle自動打開和關閉的,總是返回false)
⑤ %BULK_ROWCOUNT		返回FORALL語句更改的每個集合元素的記錄數
⑥ %BULK_EXCEPTION		返回FORALL更改的每個集合元素的記錄的異常信息

顯示遊標的4個步驟:	聲明 , 打開 , 提取記錄 , 關閉.
1)	聲明顯示遊標
CURSOR 遊標名 [(遊標參數列表)] [RETURN 返回值規範]
	IS SELECT語句
		[FOR UPDATE[OF [列名列表]]];
2)	打開顯示遊標
OPEN	顯示遊標名(參數列表);
3)	從顯示遊標中提取記錄
我們使用顯示遊標的目的就是爲了從遊標中返回或提取多行數據,然後操縱這些數據;
遊標實際就是PL/SQL中的一個虛表,我們需要從這個虛表中提取行,然後操縱行的信息
PL/SQl提供了FETCH語句執行該操作.
FETCH 遊標名 into 記錄或變量列表;
4)	關閉列表
CLOSE 遊標名;
例如:
declare 
    cursor cur_emp is select ename,sal from scott.emp;  --定義遊標
    row_emp cur_emp%rowtype;           --基於遊標定義一個記錄
begin
    open cur_emp;             --打開遊標
    fetch cur_emp into row_emp;        --從遊標中提取一行添加到記錄中
    while cur_emp%found       --循環檢測遊標屬性,看是否到最後一行
    loop
    dbms_output.put_line(row_emp.ename||'--'||row_emp.sal);
    fetch cur_emp into row_emp;             --從遊標中提取一行添加到記錄中
    end loop;
    close cur_emp;     --關閉遊標
end;
結果爲:
SMITH--800
ALLEN--1600
WARD--1250
JONES--2975
...
當我們提交一個select…for update語句時,Oracle自動對該select語句所影響的行用行級排他鎖鎖住,
CURSOR emp_cur IS
	Select empno,ename,sal,from scott.emp where job=’manager’ from update;
CURSOR emp_cur IS
	Select empno,ename,sal from scott.emp where job=’manager’ for update of sal;
我們還可以在for update後加nowait關鍵字,用於告訴oracle如果表已經被其他用戶鎖住,就不需要等待.

PL/SQL對於遊標使用過程的UPDATE和DELETE語句提供了WHERE CURRENT OF子句,使我們更容易的修改最近提取的數據行。
語法如下:
Update  表名 set  set子句 where current of 遊標名;
Delete  from 表名 where current of 遊標名.
例:
select * from scott.emp where job=('MANAGER')
declare
 cursor emp_cur is
 select empno,ename,sal from scott.emp where job='MANAGER' for update;
 emp_row emp_cur%rowtype;
 begin
      open emp_cur;
      loop
          fetch emp_cur into emp_row;
          if emp_cur%notfound  --如果遊標中沒有記錄,或者到了最後一條記錄,就退出
          then
            exit;
          else
           update scott.emp set sal=sal+1000 where current of emp_cur;   --修改當前記錄
          end if;
         end loop;
         commit;
      close emp_cur;
end;

 
 



遊標FOR循環:
FOR 記錄 IN 遊標名
LOOP
	執行語句
 END LOOP;
這裏的記錄不需要我們顯式定義的,它根據指定的遊標名,用%rowtype屬性隱式的定義的,注意,遊標FOR循環僅用在處理遊標中的每一條記錄時.
declare 
   cursor emp_cur is 
   select empno,ename,sal from scott.emp where job='MANAGER' for update;
begin 
    for emp_row in emp_cur
    Loop
    update scott.emp set sal=sal-1000 where current of emp_cur;
    end loop;
    commit;
end;
與上比較
 


*BULK COLLECT
在Oracle 8i以前,要返回多行數據只能使用顯式遊標.在Oracle 8i中引入了bulk collect子句,可以用對數據庫的一個來回,返回多行數據.
	… BULK COLLECT INTO 集合名[,集合名]…
規則:
	在oracle 9i前,我們只能在靜態SQL中使用bulk collect.在oracle9i以後,在靜態和動態SQL中都可以使用該子句.
	可以在SELECT INTO,FETCH INTO,RETURNING INTO	 子句中使用
	BULK COLLECT輸出到的集合只能存儲標量值(字符串,數字,日期等).換句話說,不能把一行數據提取到集合中的一個記錄結構的行中.
	SQL引擎自動初始化和擴展在BULK COLLECT 子句中引用的集合,它從集合的索引1開始填充,連續的插入元素,並把以前定義的任何元素值覆蓋.
	不能在FORALL語句中使用select …bulk collect語句.
	如果沒有查詢到行,select..bulk collect 不能拋出NO_DATA_FOUND異常.因此,必須檢查集合的內容,看是否有數據
	在執行查詢之前,bulk collect操作將會清空into子句引用的集合的內容.如果查詢沒有返回行,那麼集合的count方法會返回0.


現在我們用select..bulk collect into 改寫上面的顯式遊標示例
代碼如下:
declare 
 type emp_table_type is table of scott.emp%rowtype index by binary_integer;
 emp_table emp_table_type;
begin
 select * bulk collect into emp_table from scott.emp;
 for i in 1..emp_table.count
 loop
 dbms_output.put_line(emp_table(i).empno||'--'||emp_table(i).ename);
 end loop;
end;
也可以用fetch…into應用bulk collect子句
declare
     cursor cur_emp is select * from scott.emp;
     type row_emp_type is table of cur_emp%rowtype index by binary_integer;
     row_emp row_emp_type;
begin
     open cur_emp;
     fetch cur_emp bulk collect into row_emp;
     for i in 1..row_emp.count
     loop
         dbms_output.put_line(row_emp(i).empno||'--'||row_emp(i).ename);
     end loop;
     close cur_emp;
end;
結果如下
7369--SMITH
7499--ALLEN
7521--WARD
7566--JONES
7654--MARTIN
7698--BLAKE
7782--CLARK
7788--SCOTT
7839--KING
7844--TURNER
7876--ADAMS
7900--JAMES
7902--FORD
7934—MILLER





*遊標變量和REF CURSOR
遊標變量是一個指向或者引用下層遊標的變量.顯式遊標是對PL/SQL	結果集工作區命名,而遊標變量則是對該工作區的一個引用,顯式遊標和隱式遊標要綁定到特定的查詢,因而是靜態的.而遊標變量可以爲任何查詢打開,甚至在單個程序執行期間可以爲不同的查詢打開.,遊標可以在訪問遊標變量的程序之間共享.
---使用和顯式遊標基本類似;
定義REF CURSOR類型的遊標變量
語法如下:
												Return子句是可選的
TYPE	cursor_type_name 	IS		REF CURSOR[RETURN  return_type];	
			引用遊標名稱									return數據規範

弱類型的遊標變量:沒有將遊標類型與記錄數據結構相關聯,比強類型的遊標變量更有靈活性,
從oracle9i數據開始,oracle提供了一種名爲SYS_REFCURSOR的預定義的REF CURSOR,
我們可以直接按照如下方法使用,而不需要定義自己的弱類型遊標變量:
DECLARE
	my_cursor SYS_REFCURSOR;
定義一個遊標變量語法如下:
	Cursor_name cursor_type_name;
示例:
Declare
/* 爲僱員創建一個遊標類型*/
	TYPE emp_cur_type IS REF CURSOR RETURN emp%ROWTYPE;
/*爲僱員創建一個遊標變量.*/
emp_cur emp_cur_type;
BEGIN
…
END;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章