一、簡介
1、游標的概念
游標(Cursor) 就是一個變動的光標,它本質(zhì)上是一個指針,指向從數(shù)據(jù)庫查詢出來的結(jié)果集任何一條記錄,初始的時候指向第一條記錄。
2、游標的分類
Oracle中游標分為兩類:普通游標、REF游標,普通游標又可以分為兩種類型:顯式游標、隱式游標.
二、顯式游標
顯式游標是指在使用前必須有著明確的游標聲明和定義,顯式游標的定義會關(guān)聯(lián)查詢語句,返回一條或多條記錄,顯示游標的使用由開發(fā)人員控制。
1、使用步驟
1)、聲明游標
CURSOR cursor_name --聲明游標,cursor_name是游標名稱
is select_statement; --游標關(guān)聯(lián)的select語句,注意:不能是select ... into 語句
2)、打開游標
游標中想要讀取數(shù)據(jù)都是建立在游標已打開的前提下
OPEN cursor_name;
3)、讀取數(shù)據(jù)
讀取數(shù)據(jù)是使用 FETCH語句,它可以把游標指向的行記錄數(shù)據(jù)提取出來賦值給聲明的變量,注意:FETCH語句只能取出當前行的記錄,一般情況下, FETCH語句 都是搭配 循環(huán)語句 一起使用,直到某個條件不符合退出循環(huán).
FETCH cursor_name INTO v_name;
4)、關(guān)閉游標
CLOSE cursor_name;
2、示例
示例1:
declare
CURSOR cur_product --1、聲明游標
is select * from product;
v_row_product product%rowtype; --聲明product表的行變量
begin
OPEN cur_product; --2、打開游標
LOOP
FETCH cur_product INTO v_row_product; --3、讀取數(shù)據(jù)放入行變量
EXIT WHEN cur_product%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('商品名:' || v_row_product.name || '價格:' || v_row_product.price);
END LOOP;
CLOSE cur_product; --4、關(guān)閉游標
end;
示例2:
declare
CURSOR cur_product
is select name, price from product;
v_name product.name%type;
v_price product.price%type;
begin
OPEN cur_product;
LOOP
FETCH cur_product INTO v_name, v_price;
EXIT WHEN cur_product%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('商品名:' || v_name || '價格:' || v_price);
END LOOP;
CLOSE cur_product;
end;
3、顯示游標的屬性
顯示游標的屬性用于返回其執(zhí)行信息,包括:
1)ISOPEN:獲取游標是否打開,已打開返回true,沒有打開返回false
IF cur_product%ISOPEN THEN
... --游標已打開執(zhí)行的語句
ELSE
OPEN cur_product; --游標未打開則打開游標
END IF;
2)FOUND:檢查是否從結(jié)果集中提取到了數(shù)據(jù),提取到返回true,否則返回false
LOOP
FETCH cur_product INTO v_name, v_price;
IF cur_product%FOUND;
DBMS_OUTPUT.PUT_LINE('商品名:' || v_name || '價格:' || v_price);
ELSE
EXIT;
END IF;
END LOOP;
3)NOTFOUND:和FOUND相反,提取到數(shù)據(jù)返回false,未提取到數(shù)據(jù)返回true
4)ROWCOUNT:返回當前已經(jīng)提取了多少行數(shù)據(jù)
4、使用 FETCH ... BULK COLLECT INTO 語句提取全部數(shù)據(jù)
declare
CURSOR cur_product
is select * from product;
TYPE product_tab_type IS TABLE OF product%rowtype;
product_tab product_tab_type;
begin
OPEN cur_product;
FETCH cur_product BULK COLLECT INTO product_tab; --將數(shù)據(jù)全部提取出來放入product_tab
FOR i in 1..product_tab.count LOOP --循環(huán)遍歷product_tab
DBMS_OUTPUT.PUT_LINE('商品名:' || product_tab(i).name || '價格:' || product_tab(i).price);
END LOOP;
CLOSE cur_product;
end;
5、使用 FETCH ... BULK COLLECT INTO LIMIT語句提取部分數(shù)據(jù)
declare
CURSOR cur_product
is select * from product;
TYPE product_tab_type IS TABLE OF product%rowtype;
product_tab product_tab_type;
begin
OPEN cur_product;
LOOP --循環(huán)1:每次提取3行數(shù)據(jù)放入product_tab
FETCH cur_product BULK COLLECT INTO product_tab LIMIT 3;
FOR i in 1..product_tab.count LOOP --循環(huán)2:遍歷輸出product_tab中的3行數(shù)據(jù)
DBMS_OUTPUT.PUT_LINE('商品名:' || product_tab(i).name || '價格:' || product_tab(i).price);
END LOOP;
DBMS_OUTPUT.PUT_LINE('-------');
EXIT WHEN cur_product%NOTFOUND;
END LOOP;
CLOSE cur_product;
end;
6、游標FOR循環(huán)
游標的使用大部分是為了迭代結(jié)果集,在PL/SQL中有一種更方便的循環(huán)游標的方式實現(xiàn)
declare
CURSOR cur_product
is select * from product;
begin
FOR cur_info in cur_product --將游標返回的數(shù)據(jù)放入cur_info ,該變量是%rowtype類型,并且無需聲明
LOOP
DBMS_OUTPUT.PUT_LINE('商品名:' || cur_info.name || '價格:' || cur_info.price);
END LOOP;
end;
這種方式簡化了對游標的處理,使用這種情況時,Oracle會隱式地打開游標、提取數(shù)據(jù)、關(guān)閉游標.
7、帶參數(shù)的游標
使用顯示游標時可以指定參數(shù),參數(shù)可以傳遞給游標在查詢語句中使用.
參數(shù)游標的定義:
cursor cursor_name
(param_name datatype, ...)
is select_statement;
示例:
declare
v_cid product.cid%type := '1';
CURSOR cur_product
(param_id varchar2) --指定參數(shù)
is select * from product where cid = param_id; --使用參數(shù)
v_row_product product%rowtype;
begin
OPEN cur_product(v_cid); --打開游標時傳入?yún)?shù)
LOOP
FETCH cur_product INTO v_row_product;
EXIT WHEN cur_product%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_row_product.name);
END LOOP;
CLOSE cur_product;
end;
三、隱式游標
1、隱式游標的特點
隱式游標是PL/SQL自動管理的,有以下特點:
1)隱式游標有默認名稱:SQL
2)每當運行SELECT語句或者DML語句時,PL/SQL會打開一個隱式游標
3)隱式游標屬性值始終是最新執(zhí)行的SQL語句的
declare
v_name product.name%type;
begin
select p.name into v_name from product p where p.pid = '1';
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('pid為666的商品名稱為:' || v_name);
END IF;
end;
2、隱式游標的屬性
隱式游標屬性名稱和顯式游標一樣,不過其含義有區(qū)別
1)ISOPEN:由Oracle控制,永遠返回false
2)FOUND:反應(yīng)DML語句是否影響了數(shù)據(jù),有影響時返回true,否則返回false;也可以反應(yīng)SELECT INTO語句是否返回了數(shù)據(jù),返回了數(shù)據(jù)則該屬性值為true
3)NOTFOUND:和FOUND相反,DML語句沒有影響數(shù)據(jù)或SELECT INTO語句沒有返回數(shù)據(jù)時值為true,其它false
4)ROWCOUNT:反應(yīng)DML語句影響數(shù)據(jù)的數(shù)量
四、REF游標
REF CURSOR是一個游標變量,當使用顯式游標時,必須在定義部分指定其對應(yīng)的select語句,而使用REF CURSOR時,可以在打開游標時指定其對應(yīng)的select語句.
1、使用步驟
1)、定義REF CURSOR類型、游標變量
TYPE ref_type IS REF CURSOR [RETURN return_type]; --定義REF CURSOR類型
cur_name type_type; --聲明游標變量
2)、打開游標
OPEN cur_name FOR select_statement;
3)、提取數(shù)據(jù):和顯式游標使用方法一樣
4)、關(guān)閉游標:和顯式游標使用方法一樣
2、示例
declare
v_name product.name%type;
TYPE ref_type IS REF CURSOR;
cur_product ref_type;
begin
OPEN cur_product FOR select p.name from product p;
LOOP
FETCH cur_product INTO v_name;
EXIT WHEN cur_product%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_name);
END LOOP;
CLOSE cur_product;
end;
3、指定RETURN子句
如果在定義REF CURSOR類型時指定了RETURN 子句,那么在select_statement中返回的結(jié)果必須與RETURN 子句定義的記錄類型匹配.
declare
v_row_product product%rowtype;
TYPE ref_type IS REF CURSOR RETURN product%rowtype;
cur_product ref_type;
begin
OPEN cur_product FOR select * from product p; --必須是product%rowtype類型
LOOP
FETCH cur_product INTO v_row_product;
EXIT WHEN cur_product%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_row_product.name);
END LOOP;
CLOSE cur_product;
end;