今天簡單的總結一下pl/sql中cursor(游標/游標)的用法.
相信不少做開發或維護的dba在找工作的時候,遇到過類似的面視問題:請簡單的描述一下游標的型別,說一下普通游標和ref游標之間的區別,以及什麼時候該正確應用哪乙個?
這個題目,我著實難住了不少人,其實他們在具體開發的時候,也還是比較能夠把握正確的游標的使用的,但就是說不出來,當然了,這與大家自身的溝流交通能力是有關係的。有的人不善於說,但做的卻很好。扯的扯就走遠了,最後嘮叨一下:做技術這條路,能幹不能說,或者說會幹不會包裝,路是走不"遠"的.
顯式cursor
顯式是相對與隱式cursor而言的,就是有乙個明確的宣告的cursor.顯式游標的宣告類似如下(詳細的語法參加plsql ref doc )
cursor cursor_name (parameter list) is select ...
游標從declare、open、fetch、close是乙個完整的生命旅程。當然了乙個這樣的游標是可以被多次open進行使用的,顯式cursor是靜態cursor,她的作用域是全域性的,但也必須明白,靜態cursor也只有pl/sql**才可以使用她。下面看乙個簡單的靜態顯式cursor的示例:
declare上面這段匿名塊用來實現選號的功能,我們顯式的定義了乙個get_gsmno_cur,然後根據不同的號段輸出當前系統中該號短對應的可用手機號碼。當然了,實際應用中沒人這麼用的,我只是用來說應乙個顯式cursor的用法。cursor get_gsmno_cur (p_nettype in varchar2) is
select gsmno
from gsm_resource
where nettype=p_nettype and status='0';
v_gsmno gsm_resource.gsmno%type;
begin
open get_gsmno_cur('139');
loop
fetch get_gsmno_cur into v_gsmno;
exit when get_gsmno_cur%notfound;
dbms_output.put_line(v_gsmno);
end loop;
close emp_cur;
open get_gsmno_cur('138');
loop
fetch get_gsmno_cur into v_gsmno;
exit when get_gsmno_cur%notfound;
dbms_output.put_line(v_gsmno);
end loop;
close get_gsmno_cur;
end;
/
隱式cursor
隱式cursor當然是相對於顯式而言的,就是沒有明確的cursor的declare。在oracle的pl/sql中,所有的dml操作都被oracle內部解析為乙個cursor名為sql的隱式游標,只是對我們透明罷了。
另外,我們前面提到的一些迴圈操作中的指標for 迴圈,都是隱式cursor.
隱式cursor示例一:
create table zrp (str varchar2(10));隱式cursor示例二:insert into zrp values ('abcdefg');
insert into zrp values ('abcxefg');
insert into zrp values ('abcyefg');
insert into zrp values ('abcdefg');
insert into zrp values ('abczefg');
commit;
sql> begin
2 update zrp set str = 'updated' where str like '%d%';
3 ifsql%rowcount
= 0 then
4 insert into zrp values ('1111111');
5 end if;
6 end;
7 /
pl/sql procedure successfully completed
sql> select * from zrp;
str----------
updated
abcxefg
abcyefg
updated
abczefg
sql>
sql> begin
2 update zrp set str = 'updated' where str like '%s%';
3 ifsql%rowcount
= 0 then
4 insert into zrp values ('0000000');
5 end if;
6 end;
7 /
pl/sql procedure successfully completed
sql> select * from zrp;
str----------
updated
abcxefg
abcyefg
updated
abczefg0000000
6 rows selected
sql>
beginreffor rec in (select gsmno,status from gsm_resource) loop
dbms_output.put_line(rec.gsmno||'--'||rec.status);
end loop;
end;
/
cursor
ref cursor屬於動態cursor(直到執行時才知道這條查詢).
從技術上講,在最基本的層次靜態cursor和ref cursor是相同的。乙個典型的pl/sql游標按定義是靜態的。ref游標正好相反,可以動態地開啟,或者利用一組sql靜態語句來開啟,選擇哪種方法由邏輯確定(乙個if/then/else**塊將開啟乙個或其它的查詢)。例如,下面的**塊顯示乙個典型的靜態sql游標,游標c。此外,還顯示了如何通過使用動態sql或靜態sql來用ref游標(在本例中為l_cursor)來開啟乙個查詢:
declare在這段**塊中,可以看到了最顯而易見的區別:無論執行多少次該**塊,游標c總是select * from dual。相反,ref游標可以是任何結果集,因為"select * from emp"字串可以用實際上包含任何查詢的變數來代替。type rc is ref cursor;
cursor c is select * from dual;
l_cursor rc;
begin
if (to_char(sysdate,'dd') = 30) then
-- ref cursor with dynamic sql
open l_cursor for 'select * from emp';
elsif (to_char(sysdate,'dd') = 29) then
-- ref cursor with static sql
open l_cursor for select * from dept;
else
-- with ref cursor with static sql
open l_cursor for select * from dual;
end if;
-- the "normal" static cursor
open c;
end;
/
在上面的**中,宣告了乙個弱型別的ref cursor,下面再看乙個強型別(受限)的ref cursor,這種型別的ref cursor在實際的應用系統中用的也是比較多的。
/*宣告部分,以declare開頭*/
declare
v_id integer;
v_name varchar(20);
cursor c_emp is select * from employee where emp_id=3;
/*執行部分,以begin開頭*/
begin
open c_emp; --開啟游標
loop
fetch c_emp into v_id,v_name; --從游標取資料
exit when c_emp%notfound ;
end loop ;
close c_emp; --關閉游標
dbms_output.put_line(v_name);
/*異常處理部分,以exception開始*/
exception
when no_data_found then
dbms_output.put_line('沒有資料');
end ;
Oracle中Cursor 游標 學習
一 概念 游標是sql的乙個記憶體工作區,由系統或使用者以變數的形式定義。游標的作用就是用於臨時儲存從資料庫中提取的資料塊。在某些情況下,需要把資料從存放在磁碟的表中調到計算機記憶體中進行處理,最後將處理結果顯示出來或最終寫回資料庫。這樣資料處理的速度才會提高,否則頻繁的磁碟資料交換會降低效率。二 ...
游標(cursor)概念
游標 cursor 游標是系統為使用者開設的乙個資料緩衝區,存放sql語句的執行結果 每個游標區都有乙個名字 使用者可以用sql語句逐一從游標中獲取記錄,並賦給主變數,交由主語言進一步處理 主語言是面向記錄的,一組主變數一次只能存放一條記錄 僅使用主變數並不能完全滿足sql語句向應用程式輸出資料的要...
游標屬性cursor
值描述 url需使用的自定義游標的 url。注釋 請在此列表的末端始終定義一種普通的游標,以防沒有由 url 定義的可用游標。default 預設游標 通常是乙個箭頭 auto 預設。瀏覽器設定的游標。crosshair 游標呈現為十字線。pointer 游標呈現為指示鏈結的指標 乙隻手 move ...