oracle动态(参考)游标

1.分类:
静态游标:显式游标和隐式游标称为静态游标,因为在使用他们之前,游标的定义已经完成,不能再更改。
动态游标:游标在声明时没有设定,在打开时可以对其进行修改。分为强类型游标和弱类型游标。
强类型动态游标:在声明变量时使用return关键字定义游标的返回类型
弱类型动态游标:在声明变量时不使用return关键字定义游标的返回类型
一般动态游标有 REF CURSOR、REF CURSOR RETURN、SYS_REFCURSOR。
REF CURSOR RETURN 为强类型,REF CURSOR 为弱类型、SYS_REFCURSOR 为系统预定义(在STANDARD包中定义的)弱类型。

2.有如下的3种定义方式:

--支持记录类型
 type t_cur is ref cursor return emp%rowtype;
 v_cur t_cur;

 type t_weak_cur is ref cursor;
 v_cur2 t_weak_cur;
 v_cur3 sys_refcursor;

例1:强弱cursor


declare
  --定义强类型 ,返回的类型与定义的类型v_dept必须一致
  type c_dept_ref is ref cursor  return dept%rowtype;
  cur_dept c_dept_ref;
  v_dept   dept%rowtype;

begin

  open cur_dept for select * from dept;
  --动态游标,不能使用for循环
  loop
    fetch   cur_dept into v_dept;
    exit when cur_dept%notfound ;
    dbms_output.put_line(v_dept.dname);
  end loop;
  close cur_dept;
end;
/

--弱类型
declare
  type c_cursor is ref cursor;
  v_ref_cur c_cursor;
  v_emprow  emp%rowtype;
  v_deptrow  dept%rowtype;
begin

  open v_ref_cur for
    select * from dept;
  loop
    fetch v_ref_cur
      into v_deptrow;
    exit when v_ref_cur%notfound;
    dbms_output.put_line(v_deptrow.dname);
  end loop;
  close v_ref_cur;

  dbms_output.put_line('-------------------------');
  open v_ref_cur for
    select * from emp where deptno = 10;
  loop
    fetch v_ref_cur
      into v_emprow;
    exit when v_ref_cur%notfound;
    dbms_output.put_line(v_emprow.ename);
  end loop;
  close v_ref_cur;

exception
  when others then
    dbms_output.put_line(sqlerrm);
end;
/

例2:SYS_REFCURSOR

使用oracle9i提供的SYS_REFCURSOR弱类型游标,定义游标都省了....
--弱类型
declare
  v_ref_cur sys_refcursor;
  v_emprow  emp%rowtype;
  v_deptrow dept%rowtype;
begin

  open v_ref_cur for
select * from dept;

  loop
    fetch v_ref_cur
      into v_deptrow;
    exit when v_ref_cur%notfound;
    dbms_output.put_line(v_deptrow.dname);
  end loop;
  close v_ref_cur;

  dbms_output.put_line('-------------------------');
  open v_ref_cur for
    select * from emp where deptno = 10;
  loop
    fetch v_ref_cur
      into v_emprow;
    exit when v_ref_cur%notfound;
    dbms_output.put_line(v_emprow.ename);
  end loop;
  close v_ref_cur;

exception
  when others then
    dbms_output.put_line(sqlerrm);
end;
/
我们发现,为了接受可能的v_ref类型,使用了2个变量,能不能使用一个变量来直接接受v_ref的值呢? 对于弱类型的动态游标绝对不行,为什么?
如果直接使用:
  v_ref_cur sys_refcursor;
  v_ref_vlaue v_ref_cur%rowtype;
是会报错,声明问题,个人理解:因为此时的动态游标返回内容都不知道,你就直接写 v_ref_vlaue v_ref_cur%rowtype; 那么v_ref_vlaue是什么类型,接受那些值,你肯定不知道,这就违反了声明的确定性了...
而如果是强类型的动态就可以这样,因为人家已经在return里面写死了类型;

例3:可作为出参/入参


declare
   --强类型,支持记录类型
   type t_cur is ref cursor return emp%rowtype;
   v_cur t_cur;
   --自定义弱类型                
   type t_weak_cur is ref cursor;
   v_cur2 t_weak_cur;
   --系统自带弱类型
   v_cur3 sys_refcursor;  

   --使用强类型
   procedure c_get_info(p_emp_cursor t_cur) is
     v_emp_cur p_emp_cursor%rowtype;
   begin
        loop  
          fetch   p_emp_cursor into v_emp_cur;
          exit when  p_emp_cursor%notfound;
          dbms_output.put_line('强类型-'||v_emp_cur.ename); 
        end loop; 
   end;


   --使用自定义弱类型
   procedure c_get_info_weak1(p_emp_cursor t_weak_cur,choice pls_integer) is 
     --因为是弱类型,不能使用p_emp_cursor%notfound
     --必须指定具体类型
     v_emp_cur emp%rowtype;
     v_dept_cur dept%rowtype;
   begin
      if   choice=1 then
        loop  
          fetch   p_emp_cursor into v_emp_cur;
          exit when  p_emp_cursor%notfound;
          dbms_output.put_line('弱类型-'||v_emp_cur.ename); 
        end loop;  
       else
          loop  
          fetch   p_emp_cursor into v_dept_cur;
          exit when  p_emp_cursor%notfound;
          dbms_output.put_line('弱类型-'||v_dept_cur.dname); 
        end loop;  
       end if;
   end; 


   --使用系统的弱类型
   procedure c_get_info_weak2(p_emp_cursor sys_refcursor,choice pls_integer) is 
     --因为是弱类型,不能使用p_emp_cursor%notfound
     --必须指定具体类型
     v_emp_cur emp%rowtype;
     v_dept_cur dept%rowtype;
   begin
      if   choice=1 then
        loop  
          fetch   p_emp_cursor into v_emp_cur;
          exit when  p_emp_cursor%notfound;
          dbms_output.put_line('弱类型-'||v_emp_cur.ename); 
        end loop;  
       else
          loop  
          fetch   p_emp_cursor into v_dept_cur;
          exit when  p_emp_cursor%notfound;
          dbms_output.put_line('弱类型-'||v_dept_cur.dname); 
        end loop;  
       end if;
   end;


begin

  --强类型
  open  v_cur for
  select * from emp where rownum<5;
  c_get_info(v_cur);   
  --在oracle 11gR2中,支持多次打开同一个游标
  open  v_cur for
  select * from emp where rownum<5;
  c_get_info(v_cur);
  close v_cur;   
  dbms_output.put_line('-------------------------');


  --弱类型1
   open  v_cur2 for
   select * from emp where rownum<5;
   c_get_info_weak1(v_cur2,1);

   open  v_cur2 for
   select * from dept where rownum<5;
   c_get_info_weak1(v_cur2,2);
   close  v_cur2;  

   dbms_output.put_line('-------------------------');
  --弱类型2
   open  v_cur3 for
   select * from emp where rownum<5;
   c_get_info_weak2(v_cur3,1);

   open  v_cur3 for
   select * from dept where rownum<5;
   c_get_info_weak2(v_cur3,2);
   close  v_cur3; 
end;
/

例4:支持批量导入


--动态游标与bulk collect into

declare
 v_cur  sys_refcursor;
 type c_dept_tb is table of dept%rowtype;
 v_dept_tab c_dept_tb:=c_dept_tb();

begin
  open v_cur for
  select * from dept;

  fetch v_cur bulk collect into v_dept_tab;
  for x in 1 .. v_dept_tab.count loop
     dbms_output.put_line(v_dept_tab(x).dname);
  end loop;
  close v_cur;
end;
/

O(∩_∩)O~~~

猜你喜欢

转载自blog.csdn.net/u011165335/article/details/81227767