1、游標的概念
游標(CURSOR):游標是把從數據表中提取出來的數據,以臨時表的形式存放在內存中,在游標中有一個數據指針,在初始狀態下指向的是首記錄,利用fetch語句可以移動該指針,從而對游標中的數據進行各種操作。
2、游標的作用
游標是用來處理使用SELECT語句從數據庫中檢索到的多行記錄的工具。借助於游標的功能,數據庫應用程序可以對一組記錄逐條進行處理,每次處理一行。
3、游標的類型
- 顯式游標(Explicit Cursor):顯式游標需要定義聲明,在使用前要打開和獲取,使用完畢后要關閉。多用於返回多行的SELECT語句
- 隱式游標(Implicit Cursor):在執行一個SQL語句時,服務器將自動創建一個隱式游標,該游標是內存中的工作區,存儲了執行SQL語句的結果,可通過游標的屬性獲得SQL的執行結果及狀態信息。多用於只返回一行的SQL語句
4、隱式游標
(ORACLE在創建隱式游標時,默認的游標名為SQL)
1)游標的主要屬性(顯示游標、隱式游標)
- %FOUND 布爾型屬性,當SQL語句至少影響一行時為TRUE,否則為FALSE
- %NOTFOUND 布爾型屬性,當SQL語句沒有影響的行時為TRUE,否則為FALSE
- %ISOPEN 布爾型屬性,當游標已打開時返回TRUE,否則為FALSE(對用戶而言,隱式游標永遠是false)
- %ROWCOUNT 數 字型屬性,返回受到SQL影響的行數
注意:
屬性名與游標名之間沒有空格。
游標的屬性只能在PL/SQL塊中使用,而不能在SQL語句中使用
例1 將PRODUCTS表中類型為1的所有產品的單價打9折,並顯示該更新所影響的行數.
BEGIN UPDATE products SET unitprice=unitprice*0.9 WHERE categoryid=1; IF SQL%FOUND THEN dbms_output.put_line(‘更新了’||SQL%ROWCOUNT||’條記錄’); ELSE dbms_output.put_line(‘沒有更新記錄’); END IF; END;
5、顯式游標
1)定義游標
在使用顯示游標之前,必須先在聲明部分定義游標,其定義語法如下:
CURSOR cursor_name[(parameter,…)]
IS select_statement;
說明: 參數parameter形式如下:para_name [IN] data_type [:=|DEFAULT value]
(2)打開游標
當打開游標時,ORACLE會執行游標所對應的SELECT語句,並將結果存放到結果集,其定義語法如下:
OPEN cursor_name[(parameter,…)];
(3)提取數據語法如下:
FETCH cursor_name INTO variable[,…];
說明:
- 對游標第一次執行FETCH語句時,它將工作區中的第一條記錄賦給賦給變量,並使工作區內的指針指向下一條記錄。
- 工作區中的游標指針只能向下移動,不能回退。
- 在使用FETCH語句之前,必須先打開游標,才能保證工作區內有數據。
- INTO子句中的變量,順序、類型必須與工作區中每行記錄的字段數、順序以及數據類型一一對應
(4)關閉游標
關閉游標可釋放其結果集,語法如下:
CLOSE cursor_name;
說明:關閉游標,就是使游標所對應的內存工作區變為無效,並釋放與游標相關的系統資源
顯式游標——無參游標
例2:用顯式游標顯示輸出products表中供應商編號為6 的產品的信息。
DECLARE CURSOR prod_cursor IS select *from products where supplierid=6; prod_record products%rowtype; BEGIN OPEN prod_cursor; LOOP FETCH prod_cursor INTO prod_record; EXIT WHEN prod_cursor%NOTFOUND; dbms_output.put_line(‘產品編號’||prod_record.productid); dbms_output.put_line(‘產品名稱’||prod_record.productname); dbms_output.put_line(‘供應商編號’||prod_record.supplierid); END LOOP; CLOSE prod_cursor; END;
顯式游標——參數游標
例3:用顯式參數游標顯示輸出products表中供應商編號為XX 的產品的信息。
DECLARE CURSOR prod_cursor (suppID in number DEFAULT 1) IS select * from products where supplierid=suppId; prod_record products%rowtype; BEGIN OPEN prod_cursor(2); LOOP FETCH prod_cursor INTO prod_record; EXIT WHEN prod_cursor%notfound; dbms_output.put_line(‘產品編號’||prod_record.productid); dbms_output.put_line(‘產品名稱’||prod_record.productname); dbms_output.put_line(‘供應商編號’||prod_record.supplierid); END LOOP; CLOSE prod_cursor; END;
注意:在為參數游標定義參數的數據類型時,不能使用長度約束
顯式游標——游標FOR循環
語法格式:
FOR 循環變量 IN 游標類型名
LOOP
循環語句
END LOOP;
注意:
- 循環變量不需要定義,系統隱含地定義其數據類型為%ROWTYPE的變量
- 使用游標FOR循環時,不能使用OPEN、FETCH、CLOSE語句。
例4:用顯式參數游標顯示輸出products表中供應商編號為XX 的產品的信息。
DECLARE CURSOR prod_cursor (suppID in number DEFAULT 1) IS select *from products where supplierid=suppId; BEGIN FOR v_pr IN prod_cursor(3) LOOP dbms_output.put_line(‘產品編號’||v_pr.productid); dbms_output.put_line(‘產品名稱’||v_pr.productname); dbms_output.put_line(‘供應商編號’||v_pr.supplierid); END LOOP; END;
5.顯示游標與隱式游標比較
6.游標變量
游標包括顯示游標和隱式游標,在定義時與特定的查詢綁定,即在聲明中定義查詢,其結構是不變的,因此又稱靜態變量。
游標變量是一個指向多行查詢結果集的指針,不與特定的查詢綁定,可以在打開游標變量時定義查詢,可以返回不同結構的結果集。
在PL/SQL 中,使用游標變量包括定定義游標引用類型(REF CURSOR),聲明游標變量,打開游標變量、檢索游標變量、關閉游標變量等幾個基本步驟。
游標變量基本步驟:
(1) 定義游標CURSOR類型的指針
TYPE type_name IS REF CURSOR [RETURN return_type];
type_name 是新引用類型的名字
而return_type表示該游標變量返回的記錄類型。
(2) 聲明REF CURSOR類型的變量
游標變量 type_name;
(3) 打開游標變量的語法格式如下所示:
OPEN 游標變量名 FOR SELECT 語句;
(4) 檢索游標變量
檢索游標變量的方法與檢索靜態游標相似,使用 FETCH.... INTO 語句循環檢索游標變量的
結果集中的記錄。語法為:
LOOP FETCH cursor _ variable INTO variablel,variable2........; EXIT WHEN Cursor_ variables%NOTFOUND; ........ END LOOP;
檢索游標變量時只能使用簡單循環或 WHILE 循環,不能采用 FOR 循環.
(5)關閉游標變量
檢索並處理完游標變量所對應的結果集后,可以關閉游標變量,釋放存儲空間。語法為;
close 游標變量名;
游標變量的不同定義方式舉例
DECLARE 1、-- 用 %ROWTYPE類型定義游標變量的返回值. TYPE t_productsRef IS REF CURSOR RETURN products%ROWTYPE; 2、 -- 定義一個新的記錄類型 TYPE t_prodRecord IS RECORD ( prodid products.productid%TYPE, prodname products.productname%TYPE); --定義游標變量的返回值為記錄類型變量 TYPE t_prodRef IS REF CURSOR RETURN t_prodRecord;
例5:使用游標變量查詢出產品表中類別為1的產品的信息,並輸出產品名稱、類別編號、單價。
DECLARE TYPE prod_record IS RECORD ( pname products.productname%type, cid products.categoryid%type, uprice products.unitprice%type); TYPE prod_cursor IS REF CURSOR RETURN prod_reord; v_prodcur prod_cursor ; v_prodrec prod_record; BEGIN OPEN v_prodcur FOR select productname,categoryid,unitprice from products where categoryid=1; LOOP FETCH v_prodcur INTO v_prodrec ; EXIT WHEN v_prodcur%notfound; dbms_output.put_line (‘產名’||v_prodrec.pname); dbms_output.put_line(‘產品類別’||v_prodrec.cid); dbms_output.put_line (‘單價’||v_prodrec.uprice); End LOOP; Close v_prodcur; End;
使用同一游標變量打開多個查詢
例6:使用游標變量查詢出產品表中類別為1的產品的信息,然后查詢輸出產品單價小於20的產品信息。
DECLARE TYPE prod_cursor IS REF CURSOR; v_cur prod_cursor; v_rec products%rowtype; BEGIN OPEN v_cur FOR select * from products where categoryid=1; LOOP FETCH v_cur INTO v_rec; EXIT WHEN v_cur%notfound; dbms_output.put_line('產品名' || v_rec.productname); dbms_output.put_line('產品類別' || v_rec.categoryid); dbms_output.put_line('單價' || v_rec.unitprice); End LOOP; OPEN v_cur FOR select * from products where unitprice<20; LOOP FETCH v_cur INTO v_rec; EXIT WHEN v_cur%notfound; dbms_output.put_line('產品名' || v_rec.productname); dbms_output.put_line('產品類別' || v_rec.categoryid); dbms_output.put_line('單價' || v_rec.unitprice); End LOOP; Close v_cur; End;