今天在学习 REF CURSOR 游标时,百度了一下,发现很多人发了如下的一些学习类容。感觉讲的还不错,但是所举的例子可能因为作者一时大意写得有点问题(我自己做了标注)  。下面黑体字是转载的,会用红字标识出例子中的错误处!
        
Oracle 系列:REF Cursor
在上文  Oracle 系列:Cursor  (参见:http://blog.csdn.net/qfs_v/archive/2008/05/06/2404794.aspx)中
 
提到个思考:怎样让游标作为参数传递? 解决这个问题就需要用到 REF Cursor
1,什么是 REF游标
 
动态关联结果集的临时对象。即在运行的时候动态决定执行查询。
 
2
REF 游标 有什么作用?
 
实现在程序间传递结果集的功能,利用REF CURSOR也可以实现BULK SQL,从而提高SQL性能。
3,静态游标和REF 游标的区别是什么?
 
静态游标是静态定义,REF 游标是动态关联;
 
使用REF 游标需REF 游标变量。
 
REF 游标能做为参数进行传递,而静态游标是不可能的。
 
4
,什么是REF 游标变量?
 REF游标变量是一种 引用 REF游标类型  的变量,指向动态关联的结果集。
5,怎么使用  REF游标
 
声明REF 游标类型,确定REF 游标类型;
  
强类型REF游标:指定retrun typeREF 游标变量的类型必须和return type一致。
   
语法:Type   REF游标名   IS   Ref Cursor Return  结果集返回记录类型;
  
弱类型REF游标:不指定return type,能和任何类型的CURSOR变量匹配,用于获取任何结果集。
   
语法:Type   REF游标名   IS   Ref Cursor
 声明Ref 游标类型变量;
  
语法:变量名  已声明Ref 游标类型;
  
 
打开REF游标,关联结果集
  
语法:Open   Ref 游标类型变量   For   查询语句返回结果集;
  
 
获取记录,操作记录;
  
语法:Fatch    REF游标名 InTo   临时记录类型变量或属性类型变量列表;
  
 
关闭游标,完全释放资源;
  
语法:Close   REF游标名;
 
 
例子:强类型REF游标
 Declare
  Type MyRefCurA IS  REF CURSOR RETURN emp%RowType;
  Type MyRefCurB IS  REF CURSOR RETURN emp.ename%Type; --首先此处的返回类型不能这样写,“emp.ename%Type”表示的是数据类型,但是REF游标中此处的返回类型应该是记录类型。此处有两个修改方案。第一种把他改成弱类型REF;第二种是自己定义一个记录类型; 
  vRefCurA  MyRefCurA;
  vRefCurB  MyRefCurB;
  vTempA  vRefCurA%RowType;
  vTempB  vRefCurB.ename%Type; --此处定义变量的类型也有错误。如果再上面已经把MyRefCurB改为弱类型,弱类型即不规定“不规定返回类型”(这样的用法肯定是不行的);我试了一下就算是强类型也无法实现。此处我建议,不要用游标变量来规定变量的类型;可以直接定义vTempA  emp%rowtype;vTempB  emp.ename%type;
 Begin
  Open  vRefCurA  For Select  *  from   emp   Where  SAL > 2000;
  Loop
   Fatch  vRefCurA InTo  vTempA;
   Exit  When  vRefCurA%NotFound;
   DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||'  '|| vTempA.eno||'  '||vTempA.ename ||'  '||vTempA.sal) --缺少分号
  End Loop;
  Close vRefCurA;
 
  DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------');
 
  Open  vRefCurB  For Select  ename  from   emp   Where  SAL > 2000;
  Loop
   Fatch  vRefCurB InTo  vTempB;
   Exit  When  vRefCurB%NotFound;
   DBMS_OUTPUT.PUT_LINE(vRefCurB%RowCount||'  '||vTempB) --此处缺少分号
  End Loop;
  Close vRefCurB;
 
  DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------');  
 
  Open  vRefCurA  For Select  *  from   emp   Where  JOB = 'CLERK';
  Loop
   Fatch  vRefCurA InTo  vTempA;
   Exit  When  vRefCurA%NotFound;
   DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||'  '|| vTempA.eno||'  '||vTempA.ename ||'  '||vTempA.sal) --缺少分号
  End Loop;
  Close vRefCurA;
 End;

 
例子:弱类型REF游标
 /*conn scott/tiger*/
 Declare
  Type MyRefCur  IS  Ref  Cursor;
  vRefCur MyRefCur;
  vtemp  vRefCur%RowType;
 Begin
  Case(&n)
   When  1 Then Open vRefCur  For Select   *   from emp;
   When  2 Then Open vRefCur  For Select   *   from dept;
   Else
    Open vRefCur  For Select   eno,  ename  from emp Where JOB = 'CLERK';
  End Case;
  Close  vRefCur;
 End;
6,怎样让REF游标作为参数传递?
 
我把上面的例子改了一下,可以运行了。
Declare
  Type MyRefCurA IS  REF CURSOR RETURN emp%RowType;
  Type MyRefCurB IS  REF CURSOR;
  vRefCurA  MyRefCurA;
  vRefCurB  MyRefCurB;
  vTempA  vRefCurA%RowType;
  vTempB  emp.ename%type;
 Begin
  Open  vRefCurA  For Select  *  from   emp   Where  SAL > 2000;
  Loop
   Fetch  vRefCurA InTo  vTempA;
   Exit  When  vRefCurA%NotFound;
   DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||'  '|| vTempA.empno||'  '||vTempA.ename ||'  '||vTempA.sal);
  End Loop;
  Close vRefCurA;
DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------');
  Open  vRefCurB  For Select  ename  from   emp   Where  SAL > 2000;
  Loop
   Fetch  vRefCurB InTo  vTempB;
   Exit  When  vRefCurB%NotFound;
   DBMS_OUTPUT.PUT_LINE(vRefCurB%RowCount||'  '||vTempB);
  End Loop;
  Close vRefCurB;
  DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------');
  Open  vRefCurA  For Select  *  from   emp   Where  JOB = 'CLERK';
  Loop
   Fetch  vRefCurA InTo  vTempA;
   Exit  When  vRefCurA%NotFound;
   DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||'  '|| vTempA.empno||'  '||vTempA.ename ||'  '||vTempA.sal);
  End Loop;
  Close vRefCurA;
 End;