1. 程式人生 > >Oracle PL/SQL語句基礎學習筆記(下)

Oracle PL/SQL語句基礎學習筆記(下)

遊標

遊標: 遊標(cursor)可以被看作指向結果集(a set of rows)中一行的指標(pointer)。在oracle資料庫中可以使用顯示或隱式兩種遊標。

1、隱式遊標

在執行一個sql語句時,oracle伺服器將自動建立一個隱式遊標,這個遊標是記憶體中處理該語句的工作區域,其中儲存了執行SQL語句的結果.通過遊標的屬性可獲得sql語句執行的結果以及遊標狀態資訊。

遊標的主要屬性如下:

%found      布林屬性 如果sql語句至少影響一行則為true 否則為false  
%notfound   布林屬性與%found相反。  
%isopen     布林屬性遊標是否開啟 開啟為true 否則為false  
%rowcount
數字屬性返回受sql語句影響的行數

怎麼來使用這些屬性呢?
則可以通過“sql屬性名”來檢視結果

//%rowcount 用來檢查受影響的行  
SQL> declare  
     emp_row emp%rowtype;  
     begin  
     select * into emp_row from emp where empno=7369;  
     dbms_output.put_line(sql%rowcount);  
     end;  
     /  

1 //返回的結果為1  
//%found用來檢查是否影響到了行  
SQL> begin
update emp set sal=2000 where empno=7369; if sql%found then dbms_output.put_line('更新記錄成功影響了'||sql%rowcount||'行'); else dbms_output.put_line('未更新記錄'); end if; end; / 更新記錄成功 影響了1

//%notfound
//%isopen
以上兩個的使用方式參考 %found進行理解。

另外一種隱式遊標cursor for loop可用於處理sql語句的結果集

SQL> begin 
     for rec in (select * from emp) 
     loop      dbms_output.put_line(rec.empno||'/'||rec.ename||'/'||rec.job||'/'||rec.mgr||'/'||rec.hiredate||'/'||rec.sal||'/'||rec.comm||'/'||rec.deptno);  
     end loop;  
     end;  
     /  

2、顯示遊標

顯示遊標是在PL/SQL程式中使用包含select語句來宣告的遊標。如果需要處理從資料庫中檢索的一組記錄,則可以使用顯示遊標。

(1).顯示遊標處理資料四步驟

  • 宣告遊標

    宣告遊標就是通過定義遊標的名稱,遊標的特性來宣告遊標,以及開啟遊標 後就可呼叫查詢語句

語法:

Cursor cursor_name[parameter[,parameter]….]  [return return_type] is select_statement;

Parameter作為遊標的輸入引數,它可以讓使用者在開啟遊標時,向遊標傳遞值;

語法:

Parameter_name [in] datatype[{:=|default} expression]\

舉例:

 declare  
 cursor emp_cursor (pno in number(4) default 7369)  
 is select * from emp  where empno=pno; 
  • 開啟遊標

指執行宣告遊標時指定的查詢語句。開啟的方式只需使用open開啟。

語法:

Open cursor_name(引數);  

如果沒有指定引數就採用預設值執行select語句

  • 檢索資料

檢索資料就是從檢索到的結果集中獲取資料儲存到變數中,以便變數進行處理。

使用fetch語句找出結果集中的單行,並從中提取單個值傳遞給主變數。

語法:

Fetch cursor_name into [variable_list[record_variable]]

變數用於儲存檢索的資料

  • 關閉遊標

close 遊標名稱

綜上所述綜合案例如下:

SQL> declare  
     cursor emp_cursor (pno in number default 7369)   //宣告遊標  
     is select * from emp where empno=pno;    
     emp_row emp%rowtype; //宣告變數  
     begin  
         open emp_cursor(7934); //開啟遊標  
         fetch emp_cursor into emp_row; //檢索資料 結果為一行  
         dbms_output.put_line(emp_row.ename); //輸出檢索結果
         close emp_cursor; //關閉遊標  
     end;  
     /  

(2).遊標for迴圈

依次讀取結果集中的行,當for迴圈開始時,遊標會自動開啟(不需要使用open方法開啟),每迴圈讀取一次,系統自動讀取當前資料(不需要使用fetch),當退出for迴圈時,遊標也會自動關閉(不需要使用close方法)

SQL> declare  
  cursor emp_cursor (pno in number default 7369) //宣告遊標  
  is select * from emp where empno=pno;  

  begin  
     for emp_row in emp_cursor(7934) loop //for迴圈開始時 自動開啟遊標 並且自動獲取資料 自動關閉  
      dbms_output.put_line(emp_row.ename);  
     end loop;  
  end;  
  /  

(3).遊標變數

遊標變數也可以處理多行查詢結果集。

(3.1).弱ref cursor型別

遊標變數定義兩個步驟:

  • 定義cursor型別的指標

語法:

Type ref_cursor_name is ref cursor[return return_type]  

舉例:

Type var_cursor_name is ref cursor;  
  • 定義ref cursor型別的變數
v_rc var_cursor_name;  

綜合寫法如下:

Type var_cursor_name is ref cursor;  
v_rc var_cursor_name; 

上面的綜合宣告的遊標變數 稱為弱的ref cursor型別,因為它沒有指明遊標返回的結果,因此它可以指向任何一個具有多列的select查詢結果.

(3.2).強ref cursor型別

宣告:

Type varcursorName is ref cursor return emp%rowtype; //指明瞭返回的結果  
Vcn varcursorName; //宣告一個強的ref cursor型別的變數  

使用遊標變數與遊標使用方式一樣,也需要宣告,開啟,檢索,關閉遊標變數。

綜合案例如下:

 SQL> declare  
      type emp_cname is ref cursor return emp%rowtype; //宣告遊標變數第一步 
      ecname emp_cname; //宣告遊標變數第二步
      emp_row emp%rowtype; //宣告用於儲存檢索資料的變數 
      begin  
       dbms_output.put_line('開始');  
       open ecname for select * from emp where empno=7934; //開啟遊標變數  
       loop  
        fetch ecname into emp_row; //查詢結果賦值給儲存的變數  
        exit when ecname%notfound; //退出條件  
        dbms_output.put_line(emp_row.ename); //輸出結果  
       end loop; //退出迴圈  
       close ecname; //關閉遊標變數  
       dbms_output.put_line('結束');  
     end;  
     /  

開始
MILLER
結束

//複雜的案例  
SQL> declare
     type emp_cname is ref cursor return emp%rowtype;
     ecname emp_cname;
     emp_row emp%rowtype;
     begin  
       dbms_output.put_line('開始');  
       open ecname for select * from emp;  
       loop  
        fetch ecname into emp_row;  
        exit when ecname%notfound;  
        dbms_output.put_line(emp_row.ename);  
       end loop;  
       close ecname;  
     dbms_output.put_line('結束');  
    end;  
    /  

開始
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
結束

使用遊標更新資料庫

定位遊標之後進行刪除|修改指定的資料行 更新的時候需要使用for update選項。

Cursor cursor_name is select_statement;  
For update[of column[,column],[nowait]]

of用來指定要鎖定的列,如果忽略of那麼表中選擇的資料行都將鎖定。如果被鎖定行已經被鎖定了,那麼必須等待釋放才能鎖定對於這種情況我們可以使用nowait語句。

當使用for update語句宣告遊標後,可以再delete|update語句中使用where current of子句,修改|刪除遊標結果集中當前行對應的表中的資料。

語法:

where { current of cursor_name|search_condition}

舉例說明:

//修改操作  
SQL> declare
     cursor ecname is select * from emp where empno=7934  
     for update of sal nowait;
     esal number(7,2);
     begin  
       dbms_output.put_line('開始');
       for r in ecname loop  
        esal:=r.sal*10;  
        update emp set sal=esal where current of ecname;  
       end loop;
       dbms_output.put_line('結束');  
     end;  
     /  

開始
結束