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;
/
開始
結束