1. 程式人生 > 資料庫 >Oracle遊標詳解

Oracle遊標詳解

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;
    說明:關閉遊標,就是使遊標所對應的記憶體工作區變為無效,並釋放與遊標相關的系統資源
例3:用顯式遊標顯示輸出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;
例4:用顯式引數遊標顯示輸出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語句。
例5:用顯式引數遊標顯示輸出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;

 

 6.遊標變數
遊標包括顯示遊標和隱式遊標,它們都是靜態定義的,即在宣告中定義查詢。
遊標變數的定義包括兩個步驟:
(1) 定義遊標CURSOR型別的指標
 TYPE type_name IS REF CURSOR [RETURN return_type];
type_name 是新引用型別的名字
而return_type表示該遊標變數返回的記錄型別。
(2) 宣告REF CURSOR型別的變數
    遊標變數   type_name;
(3) 開啟遊標變數的語法格式如下所示:
    OPEN  遊標變數名  FOR SELECT 語句;

 

 

 

遊標變數的不同宣告方式舉例
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;
例6:使用遊標變數查詢出產品表中類別為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;

 

 

使用同一遊標變數開啟多個查詢
例5:使用遊標變數查詢出產品表中類別為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;