ORACLE遊標管理

1.       遊標: 容器,存儲SQL語句影響行數。

2.       遊標類型: 隱式遊標,顯示遊標,REF遊標。其中,隱式遊標和顯示遊標屬於靜態遊標(運行前將遊標與SQL語句關聯),REF遊標屬於動態遊標(運行時將遊標與SQL語句關聯)。

3.       隱式遊標: DML語句對應的遊標,由Oracle自動管理,也稱SQL遊標。(所有的DML操作都被Oracle內部解析爲一個cursor名爲SQL的隱式遊標)

q      隱式遊標的屬性有:

q      %FOUND – SQL 語句影響了一行或多行時爲 TRUE

q      %NOTFOUND – SQL 語句沒有影響任何行時爲TRUE

q      %ROWCOUNT – SQL 語句影響的行數

q      %ISOPEN - 遊標是否打開,始終爲FALSE

舉例說明:
Sql代碼

   1. declare 
   2.  
   3. v_empno emp.empno %type:=7000;  
   4.  
   5. begin 
   6.  
   7.    update emp set ename='fxe' where empno=v_empno;  
   8.  
   9.    if SQl%found then 
  10.  
  11.       dbms_output.put_line(SQL%rowcount||'Delete Ok!');  
  12.  
  13.    end if;  
  14.  
  15.    if SQL%notfound then -- 一條SQL就表示是一個隱式遊標  
  16.  
  17.       dbms_output.put_line('僱員編號'||v_empno||'不存在');  
  18.  
  19.    end if;  
  20.  
  21. end;

 

4. 顯示遊標操作:

                  (1)聲明遊標(關聯SQL語句)    cursor+遊標名 is/as sql語句

                  (2)打開遊標(執行SQL語句,填充遊標)    open+遊標名

                  (3)提取遊標的行    fetch 遊標名 into 行類型變量

                  (4)關閉遊標       close+遊標名

 

舉例說明:
Sql代碼

   1. declare 
   2.  
   3. cursor emp_cur is select * from emp; --聲明無參顯示遊標 關聯SQL  
   4.  
   5. empRecord emp%rowtype;  --表示類型爲一條記錄  
   6.  
   7. begin 
   8.  
   9. open emp_cur; --打開遊標  
  10.  
  11. loop  
  12.  
  13.     fetch emp_cur into empRecord; --取出emp_cur 這個遊標所對應的記錄放入empRecord變量裏  
  14.  
  15.     exit when emp_cur%notfound; --當沒記錄時,退出循環  
  16.  
  17.     dbms_output.put_line(empRecord.ename); --打印ename  
  18.  
  19. end loop;  
  20.  
  21. close emp_cur;  
  22.  
  23. end; 
 

5. 帶參數的顯示遊標

例:
 
Sql代碼

   1. declare 
   2.  
   3. destination varchar2(20);  
   4.  
   5. cursor emp_cur(dest varchar2) --聲明帶參顯示遊標  
   6.  
   7.    is select * from emp where empno=dest; --關聯到SQL  
   8.  
   9. empRecord emp%rowtype;  -- 行類弄的變量empRecord  
  10.     
  11. begin 
  12.  
  13. destination:=&empno;  --彈出用戶輸入框  
  14.  
  15. open emp_cur(destination); --打開遊標  
  16.  
  17. loop  
  18.  
  19. fetch emp_cur into empRecord; -- 循環每一遊標所對應的記錄放入empRecord  
  20.  
  21. exit when emp_cur%notfound;  
  22.  
  23. dbms_output.put_line(empRecord.ename);  
  24.  
  25. end loop;  
  26.  
  27. close emp_cur;  
  28.  
  29. end; 
 
----輸入參數:7369


6. 使用顯式遊標更新行

q      允許使用遊標刪除或更新活動集中的行

q      聲明遊標時必須使用 SELECT … FOR UPDATE語句
 

例:
Sql代碼

   1. declare 
   2.  
   3.    old_sal number(4);  
   4.  
   5.    emp_name varchar2(20);  
   6.  
   7.    cursor emp_cur is select ename,sal from emp --聲明顯示遊標,關聯SQL  
   8.  
   9.                      where sal<1000  
  10.  
  11.                      for update of sal;   -- 定義的遊標會讓數據庫對涉及的行(對應的列)加鎖,別的會話如果要訪問該遊標中的行便會進入等待狀態。  
  12.                                   --如果別的會話一直不解鎖,那麼你的select就會一直等待下去,如果你不想等,只需在for update後面加上nowait就可以解決這個問題了,這樣你的選擇會立即返回。  
  13. begin 
  14.  
  15.    open emp_cur;   
  16.  
  17.    loop  
  18.  
  19.      fetch emp_cur into emp_name,old_sal;  
  20.  
  21.      exit when emp_cur%notfound;  
  22.  
  23.      update emp set sal=1.1*old_sal  --更新數據  
  24.  
  25.      where current of emp_cur;     --作用範圍就只在你循環的當前行的範圍中了  
  26.  
  27.      dbms_output.put_line('更新成功!');  
  28.  
  29.    end loop;  
  30.  
  31. end;


 

7.循環遊標

q     循環遊標用於簡化遊標處理代碼

q     當用戶需要從遊標中提取所有記錄時使用

q     循環遊標的語法如下:

 

   
Sql代碼

   1. FOR <record_index> IN <cursor_name>  
   2.  
   3. LOOP  
   4.  
   5.        <executable statements>  
   6.  
   7. END LOOP; 

FOR <record_index> IN <cursor_name>

LOOP

       <executable statements>

END LOOP;

 

 

例:
Java代碼

   1. declare  
   2.  
   3. cursor emp_cur is select empno,ename,sal from emp; --顯示遊標  
   4.  
   5. begin  
   6.  
   7.  
   8. for empRecord in emp_cur  --empRecord 表示每行,emp_cur  所有行  
   9.  
  10. loop  
  11.  
  12.     dbms_output.put_line(empRecord.empno  
  13.  
  14.     ||empRecord.ename||empRecord.sal);  
  15.  
  16. end loop;  
  17.  
  18. end;
 

 

8.REF遊標和遊標變量

q      REF 遊標和遊標變量用於處理運行時動態執行的 SQL 查詢

q      創建遊標變量需要兩個步驟:

q      聲明 REF 遊標類型

q      聲明 REF 遊標類型的變量

q      用於聲明 REF 遊標類型的語法爲:

 

       TYPE <ref_cursor_name> IS REF CURSOR

       [RETURN <return_type>];

q      打開遊標變量的語法如下:

        OPEN cursor_name FOR select_statement;

 

聲明強類型的REF遊標

type emp_cur is ref cursor return emp%rowtype;

empRecord emp_cur;

 

聲明弱類型的REF遊標

type emp_cur is ref cursor;

empRecord emp_cur;

 

 

例:
Sql代碼

   1. DECLARE 
   2.  
   3.     TYPE emp_cur IS REF CURSOR   
   4.  
   5.           RETURN emp%ROWTYPE; -- 聲明強類型的REF遊標(只能返回emp結構類弄的遊標)  
   6.  
   7.      empObj emp_cur;    --聲明 REF 遊標類型的變量  
   8.  
   9.     empRecord emp%ROWTYPE; --行數據類開的變量  
  10.  
  11.      BEGIN 
  12.  
  13.     OPEN empObj FOR  --打開ref類型的遊標  
  14.  
  15.       SELECT * FROM emp;   
  16.  
  17.     loop  
  18.  
  19.     FETCH empObj INTO empRecord; --一行一行取出  
  20.  
  21.     exit when empObj%notfound;  
  22.  
  23.     dbms_output.put_line(empRecord.ename);  
  24.  
  25.     end loop;  
  26.  
  27.     CLOSE empObj;  
  28.  
  29.      END;

 


9.遊標變量的優點和限制

 

q      遊標變量的功能強大,可以簡化數據處理。

q      遊標變量的優點有:

q      可從不同的 SELECT 語句中提取結果集

q      可以作爲過程的參數進行傳遞

q      可以進行賦值運算

q      使用遊標變量的限制:

q      不能在程序包中聲明遊標變量(這兒指的不是聲明遊標)

q      FOR UPDATE子句不能與遊標變量一起使用

q      不能使用比較運算符

今天遇到的問題:

當使用帶參數的顯示遊標時,比如說使用的參數爲輸入參數,不能在SQL語句中直接寫輸入參數名字,否則解析不到,視爲無效。

正確的寫法:DECLARE
  CURSOR cSafeID(report_year2 NUMBER) IS
      SELECT t.accident_remark
            FROM nssrf_v_s_monthly_report t
                 WHERE t.report_year =report_year2;
  BEGIN
      OPEN cSafeID(report_year);

------------------其中report_year爲輸入參數

錯誤的寫法:

DECLARE
  CURSOR cSafeID IS
      SELECT t.accident_remark
            FROM nssrf_v_s_monthly_report t
                 WHERE t.report_year =report_year;
  BEGIN
      OPEN cSafeID;

-----------------語句中解析不到report_year的值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章