遊標是什麼:
遊標字面理解就是遊動的游標。
用資料庫語言來描述:遊標是映射在結果集中一行資料上的位置實體,有了遊標使用者就可以訪問結果集中的任意一行資料了,將遊標放置到某行後,即可對該行資料進行操作,例如提取當前行的資料等等。
遊標的分類:
顯式遊標和隱式遊標
顯示遊標的使用需要4步:
1.聲明遊標
CURSOR mycur(vartype number) is
select emp_no,emp_zc from cus_emp_basic
where com_no = vartype;
2.開啟遊標
open mycur(000627) 注:000627:參數
3.讀取資料
fetch mycur into varno,varprice;
4.關閉遊標
close mycur;
遊標的屬性:
oracle 遊標有4個屬性: %ISOPEN , %FOUND , %NOTFOUND, %ROWCOUNT
%ISOPEN 判斷遊標是否被開啟,如果開啟%ISOPEN 等於true,否則等於false
%FOUND %NOTFOUND 判斷遊標所在的行是否有效,如果有效,則%FOUNDD等於true,否則等於false
%ROWCOUNT 返回當前位置為止遊標讀取的記錄行數。
Oracle遊標迴圈
第一種使用loop 迴圈
open c_postype;
loop
fetch c_postype into v_postype,v_description ;
exit when c_postype%notfound;
……
end loop
colse c_postype;
這裡需要注意,exit when語句一定要緊跟在fetch之後。必避免多餘的資料處理。
處理邏輯需要跟在exit when之後。這一點需要多加小心。
迴圈結束後要記得關閉遊標。
第二種使用while迴圈。
open c_postype;
fetch c_postype into v_postype,v_description;
while c_postype%found loop
……
fetch c_postype into v_postype,v_description ;
end loop;
close c_postype;
我們知道了一個遊標開啟後,必須執行一次fetch語句,遊標的屬性才會起作用。所以使用while 迴圈時,就需要在迴圈之前進行一次fetch動作。
而且資料處理動作必須放在迴圈體內的fetch方法之前。迴圈體內的fetch方法要放在最後。否則就會多處理一次。這一點也要非常的小心。
總之,使用while來迴圈處理遊標是最複雜的方法。
第三種 for迴圈
for v_pos in c_postype loop
v_postype := v_pos.pos_type;
v_description := v_pos.description;
…
end loop;
可見for迴圈是比較簡單實用的方法。
首先,它會自動open和close遊標。解決了你忘記開啟或關閉遊標的煩惱。
其它,自動定義了一個記錄類型及聲明該類型的變數,並自動fetch資料到這個變數中。
我們需要注意v_pos 這個變數無需要在迴圈外進行聲明,無需要為其指定資料類型。
它應該是一個記錄類型,具體的結構是由遊標決定的。
這個變數的範圍僅僅是在迴圈體內。
把v_pos看作一個記錄變數就可以了,如果要獲得某一個值就像調用記錄一樣就可以了。
如v_pos.pos_type
由此可見,for迴圈是用來迴圈遊標的最好方法。高效,簡潔,安全。
但遺憾的是,常常見到的卻是第一種方法。所以從今之後得改變這個習慣了。
綜合樣本1
declare cursor goods_cursor --建立遊標 is select * from goods where goodsid < 5; type goods_tab is table of goods%rowtype; --聲明索引表資料類型 cur_goods_cursor goods_tab; --聲明迴圈變數 begin open goods_cursor; loop fetch goods_cursor bulk collect into cur_goods_cursor limit 3;--取三條到索引表 for i in 1..cur_goods_cursor.count loop --迴圈索引表 dbms_output.put_line(cur_goods_cursor(i).goodsid||'-'||cur_goods_cursor(i).goodsname||'-'||cur_goods_cursor(i).remark); end loop; exit when goods_cursor%notfound; end loop; close goods_cursor;end;
綜合樣本2
create or replace procedure SP_TestDemo is temp VARCHAR2(200); CURSOR C_USER IS SELECT OSNAME FROM tbaccessos;begin OPEN C_USER; LOOP FETCH C_USER INTO temp; if C_USER%NOTFOUND then dbms_output.put_line('遊標中已經沒有資料'); else dbms_output.put_line('第' || C_USER%rowcount || '條資料輸出完畢'); end if; EXIT when C_USER%NOTFOUND; dbms_output.put_line(temp ||chr(13)); END LOOP; CLOSE C_USER;end;