1. 程式人生 > >(七)Oracle學習筆記—— 遊標

(七)Oracle學習筆記—— 遊標

使用 3.3 job clerk 介紹 tput 技術分享 then emp

1.遊標簡介

  遊標用來處理從數據庫中檢索的多行記錄(使用SELECT語句)。利用遊標,程序可以逐個地處理和遍歷一次檢索返回的整個記錄集。

  為了處理SQL語句,Oracle將在內存中分配一個區域,這就是上下文區。這個區包含了已經處理完的行數、指向被分析語句的指針,整個區是查詢(select)語句返回的數據行集。遊標就是指向上下文區句柄或指針。

2.遊標使用

  2.1 定義一個遊標

CURSOR cursor_name IS select_statement;

例如:把數據表中emp中部門號為20的員工定義為遊標:

CURSOR exce_emp is select
* from scott.emp where deptno=20;

註意:在聲明遊標時,select_statement不能包含INTO子句。當使用顯示遊標時,INTO子句是FETCH語句的一部分。

  2.2 為查詢打開遊標

打開遊標實際上是從數據表中讀取數據的過程,在這個過程中主要完成兩件事:

①把select查詢結果讀入內存工作區中。

②將遊標指針定位在第一條記錄。

OPEN cursor_name

  2.3 取得結果放入PL/SQL變量中(利用fetch命令從遊標中提取數據)

FETCH命令首先將當前遊標指針所指的行讀出來並且置於相應的變量中,然後把遊標指針移到下一行。所以FETCH命令每一個執行的時候,只能提取一行或者部分的數據。

FETCH cursor_name INTO list_of_variables;  --變量(變量名1,變量名2......)
FETCH cursor_name INTO PL/SQL_record;    --記錄型變量名

  2.4 關閉遊標

CLOSE cursor_name

舉例:

declare
   cursor exce_emp is select * from emp where empno=6676;            --定義遊標
   var_exce_emp exce_emp%rowtype;          --定義變量
begin
open exce_emp; --打開遊標 fetch exce_emp into var_exce_emp; --fetch提取數據 dbms_output.put_line(提取的數據為:員工的姓名:||var_exce_emp.ename||,員工的工作為:||var_exce_emp.job); close exce_emp; end;

3.遊標的屬性

針對2.3,如果遊標指針已經指到了遊標的末尾,那麽FETCH命令將讀不到數據了,所以有這樣一種機制,這種機制可以測出遊標是否已經指到了遊標的末尾。這種機制就是遊標的屬性。

遊標有四個屬性:%FOUND、%ISOPEN、%NOTFOUND、%ROWCOUNT

  3.1 %FOUND

該屬性用於測試在自己所在語句之前的最後一個FETCH命令是否提取到了數據。如果能夠提取到數據就返回true,否則返回false。但是如果一個遊標還沒有被打開就運用%FOUND,那麽將會產生INVALID_CURSOR異常。

declare
   cursor exce_emp is select empno,ename from emp where deptno=20;
   var_exce_emp exce_emp%rowtype;
   i int := 1;
begin
  open exce_emp;
  loop
    fetch exce_emp into var_exce_emp;
    if exce_emp %found then        --利用%found屬性檢測是否提取到了數據
      dbms_output.put_line(||to_char(i)||個員工的信息-------編號:||var_exce_emp.empno||員工姓名:||var_exce_emp.ename);
      i := i+1;
    else
      exit;
    end if;
  end loop;
  close exce_emp;
end;

  3.2 %ISOPEN

該屬性主要用於測試遊標是否已經打開。

declare
   cursor exce_emp is select empno,ename from emp;
   var_exce_emp exce_emp%rowtype;
begin
  if not exce_emp%isopen then        --檢測遊標是否已經打開
    dbms_output.put_line(遊標沒有打開);
    open exce_emp;
  else
    dbms_output.put_line(遊標已經打開了);
  end if;
end;

  3.3 %NOTFOUND

fetch是否提到數據 沒有true 提到false。

  3.4 %ROWCOUNT

已經取出的記錄的條數

當剛剛打開遊標時,%ROWCOUNT的值為0。每運行一次FETCH命令,%ROWCOUNT的值就會自增1。因此%ROWCOUNT的值可以看著是遊標中當前被讀取了的記錄的條數,即遊標循環中處理的當前行數。如果一個有遊標在打開之前調用%ROWCOUNT屬性,就會產生異常INVALID_CURSOR。

declare
  cursor exce_emp is empno,ename from emp where deptno=20;
  var_exce_emp exce_emp%rowtype;
  n int := 5;
begin
  open exce_emp;
  loop
    fetch exce_emp into var_exce_emp;
    exit when exce_emp%notfound;
    dbms_output.put_line(員工號:||var_exce_emp.empno||,員工姓名:||var_exce_emp.ename);
    exit when exce_emp%rowcount=n;
  end loop;
  close exce_emp;
end;

4.隱式遊標

【2.遊標使用】介紹的都是顯式遊標。Oracle還默認了一種遊標,這個遊標就是隱式遊標,隱式遊標是不需要打開和關閉的。其被定義為SQL。它同時也具有4個屬性。

declare
  tempdeptno := 20;
  counts int := 0;
begin
  update emp set job=CLERK where deptno = tempdeptno;
  if sql%found then
    counts := sql%rowcount;
  end if;
  dbms_output.put_line(||to_char(counts)||行語句做了修改);
end;

顯式遊標和隱式遊標的區別:

      技術分享

5.遊標的常見操作

  5.1 FOR循環遊標 (常用的一種遊標)

--<1>定義遊標
 --<2>定義遊標變量
 --<3>使用for循環來使用這個遊標

  --前向遊標 只能往一個方向走
  --效率很高
      declare
        --類型定義
        cursor cc is select empno,ename,job,sal
         from emp where job = MANAGER;
        --定義一個遊標變量
        ccrec cc%rowtype;
      begin
         --for循環
         for ccrec in cc loop
            dbms_output.put_line(ccrec.empno||-||ccrec.ename||-||ccrec.job||-||ccrec.sal);
         end loop;       
      end;

  5.2 FETCH遊標

 --使用的時候 必須要明確的打開和關閉
      declare
        --類型定義
        cursor cc is select empno,ename,job,sal
         from emp where job = MANAGER;
        --定義一個遊標變量
        ccrec cc%rowtype;
      begin
        --打開遊標
         open cc;
        --loop循環
         loop
            --提取一行數據到ccrec中 
            fetch cc into ccrec;         
            --判斷是否提取到值,沒取到值就退出
            --取到值cc%notfound 是false
            --取不到值cc%notfound 是true 
            exit when cc%notfound;
            dbms_output.put_line(ccrec.empno||-||ccrec.ename||-||ccrec.job||-||ccrec.sal);            
         end loop; 
        --關閉遊標
         close cc;  
      end;

  5.3 參數遊標

--按部門編號的順序輸出部門經理的名字
     declare
       --部門
       cursor c1 is select deptno from dept;
       --參數遊標c2,定義參數的時候
       --只能指定類型,不能指定長度  
       --參數只能出現在select語句=號的右側
       cursor c2(no number,pjob varchar2) is select emp.* from emp
         where deptno = no and job=pjob;
       c1rec c1%rowtype;
       c2rec c2%rowtype;
       --定義變量的時候要指定長度
       v_job varchar2(20);
     begin
       --部門
        for c1rec in c1 loop
          --參數在遊標中使用
          for c2rec in c2(c1rec.deptno,MANAGER) loop
            dbms_output.put_line(c1rec.deptno||-||c2rec.ename);
          end loop; 
        end loop; 
     end; 

  5.4 引用遊標 / 動態遊標

-- select語句是動態的
     declare
       --定義一個類型(ref cursor)弱類型    
       type cur is ref cursor;
         --強類型(返回的結果集有要求)
       type cur1 is ref cursor return emp%rowtype;
       --定義一個ref cursor類型的變量   
       cura cur;
       c1rec emp%rowtype;
       c2rec dept%rowtype;
     begin
  DBMS_output.put_line(輸出員工)   ;       
       open cura for select * from emp;
       loop
         fetch cura into c1rec;   
         exit when cura%notfound;
         DBMS_output.put_line(c1rec.ename)   ;
       end loop ;
  DBMS_output.put_line(輸出部門)   ;
       open cura for select * from dept;
       loop
         fetch cura into c2rec;   
         exit when cura%notfound;
         DBMS_output.put_line(c2rec.dname)   ;
       end loop;  
       close cura;
    end;

(七)Oracle學習筆記—— 遊標