1. 程式人生 > >Oracle中的遊標的原理和使用詳解

Oracle中的遊標的原理和使用詳解

declare
  sname varchar2( 20); --宣告變數
  cursor student_cursor is select sname from student ; --宣告遊標
begin
  open student_cursor;                 --開啟遊標
  fetch student_cursor into sname;     --讓遊標指標往下移動
  while student_cursor%found           --判斷遊標指標是否指向某行記錄
  loop --遍歷
    dbms_output.put_line ('學生姓名' ||sname );
    fetch student_cursor into sname;
  end loop;
  close student_cursor;
end;
      
------------------------------------有引數遊標-------------------------------
declare
  sname student.sname%type;
  sno student.sno%type;
  cursor student_cursor (input_sno number) is 
  select s.sname, s.sno from student s where s.sno > input_sno; --宣告帶引數的遊標
begin
  sno := &請輸入學號;                     --要求從客戶端輸入引數值,"&"相當於佔位符;
  open student_cursor( sno);             --開啟遊標,並且傳遞引數
  fetch student_cursor into sname, sno;  --移動遊標
  while student_cursor% found
  loop
    dbms_output.put_line ('學號為:' ||sno ||'姓名為:' ||sname );
    fetch student_cursor into sname,sno;
  end loop;
  close student_cursor;
end;


------------------------------------循環遊標-------------------------------    
-- Created on 18-1月-15 by 永文
declare
  stu1 student%rowtype ;       --這裡也不需要定義變數來接收fetch到的值
  cursor student_cursor is select * from student ;
begin
  open student_cursor;         --這裡不需要開啟遊標
  for stu1 in student_cursor
  loop
    dbms_output.put_line ('學生學號:' ||stu1.sno ||'學生姓名:' ||stu1.sname );
    fetch student_cursor into stu1;   --也不需要fetch了
  end loop;
  close student_cursor;               --這裡也不需要關閉遊標
end;


------------------------------------使用遊標更新行-------------------------------   
declare
stu1 student%rowtype ;
cursor student_cursor is select * from student s where s.sno in (2 ,3 ) for update;--建立更新遊標
begin
  open student_cursor;
  fetch student_cursor into stu1;--移動遊標
  while student_cursor%found --遍歷遊標,判斷是否指向某個值
  loop
    update student set sage = sage + 10 where current of student_cursor;--通過遊標中的資訊更新資料
    fetch student_cursor into stu1;--移動遊標
  end loop;
  close student_cursor;
end;
 

declare
  stu1 student%rowtype ;
  cursor student_cursor is select * from student s where s.sno in (2 ,3 ) for update;--建立更新遊標
begin
  open student_cursor;
  -- fetch student_cursor into stu1;--移動遊標
  -- while student_cursor%found--遍歷遊標,判斷是否指向某個值
  loop
    fetch student_cursor into stu1 ;--移動遊標
    exit when student_cursor %notfound ;
    update student set sage = sage + 10 where current of student_cursor;--通過遊標中的資訊更新資料
  end loop;
  close student_cursor;
end;


------------------------------------使用fetch ... bulk collect into-------------------------------   
declare
  cursor   my_cursor is select ename from emp where deptno= 10; --宣告遊標
  type   ename_table_type is table of varchar2 (10 );--定義一種表型別,表中的屬性列為varchar2型別
  ename_table  ename_table_type;--通過上面定義的型別來定義變數
begin
  open   my_cursor; --開啟遊標
  fetch my_cursor bulk collect into   ename_table; --移動遊標
  for   i in 1 ..ename_table.count  loop
     dbms_output.put_line(ename_table(i));
  end   loop ;
  close my_cursor;
end;
 
 
-----------------------------------顯示遊標題目--------------------------------------
 
SQL > select * from student ;
        XH XM
---------- ----------
         1 A
         2 B
         3 C
         4 D
 
SQL > select * from address ;
        XH ZZ
---------- ----------
         2 鄭州
         1 開封
         3 洛陽
         4 新鄉
         
完成的任務 :給表student新增一列zz ,是varchar2 (10 )型別;
再從address中,將zz欄位的數值取出來,對應的插入到
student新增的zz列中。
即:得到的結果:student表中,是:
          XH XM         ZZ
         -- ---------- ------
          1 A          開封
          2 B          鄭州
          3 C          洛陽
          4 D          新鄉
 
 
declare
  stu1 student %rowtype ;
  add1 address %rowtype ;
  cursor student_cursor is select * from student for update; --宣告更新遊標
  cursor address_cursor is select * from address ;           --宣告遊標
begin
  open student_cursor ;                --開啟遊標
  fetch student_cursor into stu1;      --移動遊標
  while student_cursor% found--判斷遊標是否指向某條記錄
  loop
    open address_cursor ;              --開啟另外一個遊標
    fetch address_cursor into add1 ;   --移動遊標
    while address_cursor %found--判斷遊標是否指向某條記錄
    loop
      if add1.xh = stu1.xh then--判斷兩個遊標所指向的記錄中xh的值是否相等
        update student s set s.zz = add1.zz where current of student_cursor; --假如相等就更新遊標所指向的記錄值
      end if;
      fetch address_cursor into add1 ; --移動遊標
    end loop;
    close address_cursor ;             --關閉遊標
    fetch student_cursor into stu1 ;   --移動遊標
  end loop;
  close student_cursor ;               --關閉遊標
end;
REF遊標也叫動態遊標:
qREF 遊標和遊標變數用於處理執行時動態執行的 SQL 查詢 q建立遊標變數需要兩個步驟: q宣告 REF 遊標型別 q宣告 REF 遊標型別的變數 q用於宣告 REF 遊標型別的語法為:
TYPE <ref_cursor_name> IS REF CURSOR
[RETURN <return_type>];
-----------------------------------ref遊標---------------------------------
declare
  type ref_cursor  is ref cursor; --宣告一個ref遊標型別
  tab_cursor ref_cursor ;--宣告一個ref遊標
  sname student.xm %type ;
  sno student.xh %type ;
  tab_name varchar2 (20 );
begin
  tab_name := '&tab_name'; --接收客戶輸入的表明
  if tab_name = 'student' then
    open tab_cursor for select xh ,xm  from student ; --開啟ref遊標
    fetch tab_cursor into sno ,sname ;--移動遊標
    while tab_cursor %found
    loop
      dbms_output.put_line ('學號:' ||sno ||'姓名:' ||sname );
      fetch tab_cursor into sno ,sname ;
    end loop;
    close tab_cursor ;
  else
    dbms_output.put_line ('沒有找到你想要找的表資料資訊' );
  end if;
end;
 
  
-----------------------------------ref遊標題目---------------------------------
SQL > select * from student ;
        XH KC
---------- ----------
         1 語文
         1 數學
         1 英語
         1 歷史
         2 語文
         2 數學
         2 英語
         3 語文
         3 英語
9 rows selected
 
SQL >       
完成的任務 :
生成student2表 (xh number, kc  varchar2 (50 ));
對應於每一個學生,求出他的總的選課記錄,把每個學生的選課記錄插入到student2表中。
即,student2中的結果如下:
                      XH KC
                 --- -------------------------------------------
                       1 語文數學英語歷史
                       2 語文數學英語
                       3 語文英語
 
create table student2 (xh number, kc varchar2 (50 ));
 
declare
  kcs varchar2 (50 );
  kc varchar2 (50 );
  type ref_cursor is ref cursor; --宣告一個ref遊標型別
  stu_cursor ref_cursor ;--定義一個ref遊標型別的變數
  type tab_type is table of number; --宣告一個table型別
  tab_xh tab_type ;--定義一個表型別的變數
  cursor cursor_xh is select distinct( xh) from student; --宣告一個遊標
begin
  open cursor_xh; --開啟遊標
  fetch cursor_xh bulk collect into tab_xh; --提取資料到表中
  for i in 1 .. tab_xh.count
  loop
    kcs :='' ;
    open stu_cursor for select kc from student s where s.xh = tab_xh(i ); --開啟ref遊標
    fetch stu_cursor into kc ; --移動遊標
    while stu_cursor %found
    loop
      kcs := kc ||kcs ; --連線字串使用||而不是+
      fetch stu_cursor into kc ; --移動遊標
    end loop;
    insert into student2 (xh , kc ) values( i, kcs);
    close stu_cursor ;
  end loop;
  close cursor_xh ;
end;