zoukankan      html  css  js  c++  java
  • ref 游标(动态游标)

    转自:http://blog.sina.com.cn/s/blog_55dbebb00100gxsc.html

    自:http://blog.csdn.net/qfs_v/archive/2008/05/07/2410308.aspx

    注意:这篇文章的可取之处是定义很好,但是举的例子不能执行,由于我现在也是入门,还没有修改的能力。很怀疑作者是有意的,故意让读者执行不了。

    在上文  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 type,REF 游标变量的类型必须和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;
      vRefCurA  MyRefCurA;
      vRefCurB  MyRefCurB;
      vTempA  vRefCurA%RowType;
      vTempB  vRefCurB.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游标
     
     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 ;
      vRefCurA  MyRefCurA;
      vRefCurB  MyRefCurA;
      vTempA  emp%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;

    2.

    1.要执行返回 REF CURSOR 的存储过程,必须在 OracleParameterCollection 中定义参数,包括 CursorOracleType 以及 OutputDirection。 数据提供程序只支持作为输出参数绑定 REF CURSOR。

    示例:

    REF CURSOR 示例(使用 Oracle Scott/Tiger 架构中定义的表)

    创建 Oracle 包和包正文

    复制代码
    CREATEORREPLACE PACKAGE CURSPKG AS
    TYPE T_CURSOR
    IS REF CURSOR;
    PROCEDURE OPEN_ONE_CURSOR (N_EMPNO INNUMBER,
    IO_CURSOR
    IN OUT T_CURSOR);
    PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
    DEPTCURSOR OUT T_CURSOR);
    END CURSPKG;
    /
    复制代码
    复制代码
    CREATEORREPLACE PACKAGE BODY CURSPKG AS
    PROCEDURE OPEN_ONE_CURSOR (N_EMPNO INNUMBER,
    IO_CURSOR
    IN OUT T_CURSOR)
    IS
    V_CURSOR T_CURSOR;
    BEGIN
    IF N_EMPNO <>0
    THEN
    OPEN V_CURSOR FOR
    SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
    FROM EMP, DEPT
    WHERE EMP.DEPTNO = DEPT.DEPTNO
    AND EMP.EMPNO = N_EMPNO;

    ELSE
    OPEN V_CURSOR FOR
    SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
    FROM EMP, DEPT
    WHERE EMP.DEPTNO = DEPT.DEPTNO;

    ENDIF;
    IO_CURSOR :
    = V_CURSOR;
    END OPEN_ONE_CURSOR;

    PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
    DEPTCURSOR OUT T_CURSOR)
    IS
    V_CURSOR1 T_CURSOR;
    V_CURSOR2 T_CURSOR;
    BEGIN
    OPEN V_CURSOR1 FORSELECT*FROM EMP;
    OPEN V_CURSOR2 FORSELECT*FROM DEPT;
    EMPCURSOR :
    = V_CURSOR1;
    DEPTCURSOR :
    = V_CURSOR2;
    END OPEN_TWO_CURSORS;
    END CURSPKG;
    /
    复制代码

    示例:OracleDataReader 中的 REF CURSOR 参数

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Configuration;
    using System.Data;
    using System.Data.OracleClient;
    namespace pro
    {
    publicpartialclass WebForm4 : System.Web.UI.Page
    {
    string OracleConnectionString = ConfigurationManager.ConnectionStrings["scott"].ConnectionString;
    protectedvoid Page_Load(object sender, EventArgs e)
    {
    OracleConnection conn
    =new OracleConnection(OracleConnectionString);
    OracleCommand comm
    =new OracleCommand();
    comm.Connection
    = conn;
    comm.CommandType
    = CommandType.StoredProcedure;
    comm.CommandText
    ="curspkg.open_one_cursor";
    comm.Parameters.Add(
    new OracleParameter("n_empno", OracleType.Number)).Value ="0";
    comm.Parameters.Add(
    new OracleParameter("io_cursor", OracleType.Cursor)).Direction = ParameterDirection.Output;
    conn.Open();
    OracleDataReader rdr
    = comm.ExecuteReader();
    GridView1.DataSource
    = rdr;
    GridView1.DataBind();
    conn.Close();
    }
    }
    }
    复制代码

    示例:使用 OracleDataReader 从多个 REF CURSOR 检索数据

    按 Ctrl+C 复制代码
    按 Ctrl+C 复制代码
  • 相关阅读:
    oracle各个版本的exp/imp兼容性
    AJAX开发 下载和安装ATF的步骤
    页面省略显示——web
    Oracle数据库中分区表的操作方法
    Hashtable的使用(2)
    RMAN之实战RMAN备份
    oracle_索引使用简介
    oracle中rollback的使用方法
    Hashtable的使用
    startup 出现的监听错误或者未初始化服务句柄【数据库归档问题】
  • 原文地址:https://www.cnblogs.com/changbaishan/p/3023216.html
Copyright © 2011-2022 走看看