Oracle-遊標的種類、語法、屬性及使用,NO_DATA_FOUND和%NOTFOUND的區別

一、遊標的分類

Oracle數據庫提供了倆種遊標類型,分別爲靜態遊標和動態遊標,而靜態遊標又分爲隱士遊標和顯式遊標,動態遊標分爲弱類型和強類型倆種。


二、靜態遊標

1、顯式遊標
1).聲明遊標語法:

cursor 遊標名 [(遊標輸入參數1[,遊標輸入參數2]…)]
[return 返回類型] is 查詢語句

遊標名:指定義的遊標名稱,一般採用cursor_名稱這種命名格式。
遊標輸入參數:爲遊標指定輸入參數,注意指定參數類型時,不能約束長度,比如NUMBER(10)是錯誤的。
返回類型:表示遊標提取的一行數據的類型
查詢語句:遊標所使用的查詢語句
遊標參數和返回類型用[]圈起來表示是可以省略的條件,聲明遊標時可以不加這倆個參數

2).打開遊標語法:
open 遊標名 [所有定義的遊標輸入參數]

3).提取遊標語法:
fetch 遊標名 into 接收變量

4).關閉遊標語法:
close 遊標名

使用示例:

--檢索EMP表中的所有JOB爲MANAGER的僱員信息
DECLARE
  /*聲明遊標、(遊標輸入參數變量爲VAR_JOB)可選項*/
  CURSOR CUR_EMP(VAR_JOB IN VARCHAR2:='SALESMAN') IS
    /*遊標所使用的查詢語句*/
    SELECT EMPNO, ENAME, SAL FROM EMP WHERE JOB = VAR_JOB;
  /*聲明一個RECORD類型的記錄變量*/
  TYPE RECORD_EMP IS RECORD(
    VAR_EMPNO EMP.EMPNO%TYPE,
    VAR_ENAME EMP.ENAME%TYPE,
    VAR_SAL   EMP.SAL%TYPE);
  EMP_ROW RECORD_EMP;
BEGIN
  /*打開遊標,指定輸入參數值爲MANAGER*/
  OPEN CUR_EMP('MANAGER');
  /*將遊標指向結果集第一行數據並存入RECORD記錄變量*/
  FETCH CUR_EMP
    INTO EMP_ROW;
  /*如果遊標有數據就循環*/
  WHILE CUR_EMP%FOUND LOOP
    DBMS_OUTPUT.PUT_LINE('僱員編號:' || EMP_ROW.VAR_EMPNO || ' 僱員姓名:' ||
                         EMP_ROW.VAR_ENAME || ' 僱員薪水:' || EMP_ROW.VAR_SAL);
    /*將遊標指向結果集下一條數據*/
    FETCH CUR_EMP
      INTO EMP_ROW;
  END LOOP;
  /*關閉遊標*/
  CLOSE CUR_EMP;
END;

--另一種方式,使用%ROWTYPE類型
DECLARE
  CURSOR CUR_EMP IS
    /*使用FETCH+%ROWTYPE查詢這裏的查詢字段必須和表中字段順序及數量一致*/
    SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO FROM EMP;
  /*定義一個%ROWTYPE接收變量*/
  VAR_EMP_TYPE EMP%ROWTYPE;
BEGIN
  OPEN CUR_EMP;
  FETCH CUR_EMP
    INTO VAR_EMP_TYPE;
  WHILE CUR_EMP%FOUND LOOP
    DBMS_OUTPUT.PUT_LINE('僱員編號:' || VAR_EMP_TYPE.EMPNO || ' 僱員姓名:' ||
                         VAR_EMP_TYPE.ENAME || ' 僱員薪水:' ||
                         VAR_EMP_TYPE.SAL);
    FETCH CUR_EMP
      INTO VAR_EMP_TYPE;
  END LOOP;
  CLOSE CUR_EMP;
END;

顯示遊標具有以下屬性:

這裏寫圖片描述

2、隱式遊標

PL/SQL爲所有SQL數據操縱語句(包括返回一行的SELECT)隱士聲明遊標,稱爲隱式遊標的原因是用戶不能直接命名和控制此類遊標。當用戶在PL/SQL中使用數據操縱語言(DML)時,Oracle預先定義一個名爲SQL的隱士遊標,通過檢查隱式遊標的屬性可以獲取與最近執行的SQL語句相關的信息。

隱式遊標屬性表如下:

這裏寫圖片描述

使用示例:

--將EMP表中SALESMAN的工資加100,使用隱士遊標sql的%rowcount屬性輸出增加工資的員工數量

DECLARE

BEGIN
  UPDATE EMP SET SAL = SAL + 100 WHERE JOB = 'SALESMAN';
  IF SQL%NOTFOUND THEN
    DBMS_OUTPUT.PUT_LINE('沒有符合條件的僱員');
  ELSE
    DBMS_OUTPUT.PUT_LINE('上調了:' || SQL%ROWCOUNT || '個僱員的工資');
  END IF;
END;

三、動態遊標

靜態遊標在使用時,使用的查詢語句已經確定,如果需要在運行的時候動態的絕對執行哪種查詢,可以使用REF遊標(動態遊標)和遊標變量。

1).聲明遊標的語法
聲明REF遊標需要2個步驟:聲明REF的遊標類型和聲明使用此類型的遊標變量。

聲明遊標類型的語法:
type 遊標類型名稱 is ref cursor
[return 遊標返回值類型]

遊標類型名稱:定義的一個遊標變量的類型,一般採用ref_type_類型名 這種格式。
遊標返回值類型:可選項,定義遊標變量的返回值類型,注意必須爲記錄變量。

REF遊標分爲強類型和弱類型倆種,在定義遊標變量類型時,如果指定了遊標變量的返回值類型,那麼就是強類型,如果沒指定,就是弱類型。並且一旦指定了返回值類型,在打開遊標時,綁定的查詢結果的返回集一定是return中定義的類型.

聲明遊標變量的語法:
遊標變量名稱 遊標類型名稱

2).打開遊標的語法:
open 遊標變量名 for 查詢語句

3).提取遊標,同顯式遊標。
4).關閉遊標同顯式遊標。

使用示例:

--弱類型
--將薪水低於3000的僱員薪水增加500,增加後最高不超過3000
DECLARE
  TYPE REF_CURSOR_TYPE IS REF CURSOR; --聲明一個弱類型的動態遊標類型
  REF_CURSOR REF_CURSOR_TYPE; --定義一個遊標爲聲明的弱類型遊標
  V_SAL      EMP.SAL%TYPE;--聲明一個變量用來接收僱員薪水
  V_EMPNO    EMP.EMPNO%TYPE;--聲明一個變量用來接收僱員編號
BEGIN
  OPEN REF_CURSOR FOR
    SELECT SAL, EMPNO FROM EMP;--打開遊標並指定使用的SQL語句
  LOOP
    FETCH REF_CURSOR
      INTO V_SAL, V_EMPNO;--將遊標指向一行數據並給變量賦值
    EXIT WHEN REF_CURSOR%NOTFOUND;--當遊標無數據時退出
    IF V_SAL < 3000 THEN--薪水低於3000進入IF,這個IF最後會執行更新SQL
      IF V_SAL >= 2500 THEN--薪水低於3000又大於2500進入這個IF
        V_SAL := 3000;
      ELSE
        V_SAL := V_SAL + 500;
      END IF;--結束一個IF,一個IF對應一個END IF;
      UPDATE EMP SET SAL = V_SAL WHERE EMPNO = V_EMPNO;--更新僱員薪水
    END IF;--結束最外層IF
  END LOOP;--結束LOOP循環
  CLOSE REF_CURSOR;--關閉遊標
END;

--強類型
--查詢所有僱員姓名
DECLARE
  TYPE EMP_REF_CURSOR IS REF CURSOR RETURN EMP%ROWTYPE;--聲明一個強類型(指定返回類型)的動態遊標
  REF_CURSOR   EMP_REF_CURSOR;--定義一個聲明的強類型遊標
  V_EMP_RECORD EMP%ROWTYPE;--定義一個接收變量
BEGIN
  OPEN REF_CURSOR FOR
    SELECT * FROM EMP;
  LOOP
    FETCH REF_CURSOR
      INTO V_EMP_RECORD;
    EXIT WHEN REF_CURSOR%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(V_EMP_RECORD.ENAME);
  END LOOP;
  CLOSE REF_CURSOR;
END;

四、通過for語句循環遊標

使用for語句循環遊標可以簡化顯式遊標的處理代碼。for語句循環遊標隱式的打開遊標,自動從活動集獲取行、然後在處理完所有行時關閉遊標。循環遊標自動創建%ROWTYPE類型的變量並將此變量用做記錄索引。

語法:
for 記錄變量 in 遊標變量
loop
//操作記錄變量
end loop;

記錄變量是PL/SQL聲明的記錄變量,此變量的屬性聲明爲%ROWTYPE類型,作用域在for循環之內,for循環之外不能訪問此變量。

for語句循環遊標特性:
1、在從遊標中提取了所有記錄之後自動終止。
2、提取和處理遊標中的每一條記錄。
3、如果在提取之後%NOTFOUND屬性返回TRUE,則終止循環。如果未返回行,則不進入循環。

使用示例:

--查詢所有僱員姓名
DECLARE
  CURSOR EMP_CURSOR IS SELECT * FROM EMP;
BEGIN
  /*使用for語句循環遊標無需手動打開/關閉遊標*/
  FOR V_EMP_RECORD IN EMP_CURSOR LOOP
    DBMS_OUTPUT.PUT_LINE(V_EMP_RECORD.ENAME);
  END LOOP;
END;

五、NO_DATA_FOUND和%NOTFOUND的區別

1、SELECT…INTO語句返回0條和多條記錄時觸發NO_DATA_FOUND。
2、當UPDATE或DELETE語句的WHERE子句未找到時觸發%NOTFOUND。
3、在提取循環中要用%NOTFOUND或%FOUND來確定循環的退出條件,不要使用NO_DATA_FOUND。

發佈了50 篇原創文章 · 獲贊 305 · 訪問量 83萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章