zoukankan      html  css  js  c++  java
  • REF Cursor 游标


    转自: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 包和包正文




    复制代码
    CREATE OR REPLACE PACKAGE CURSPKG AS
    TYPE T_CURSOR
    IS REF CURSOR;
    PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
    IO_CURSOR
    IN OUT T_CURSOR);
    PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
    DEPTCURSOR OUT T_CURSOR);
    END CURSPKG;
    /

    复制代码



    复制代码
    CREATE OR REPLACE PACKAGE BODY CURSPKG AS
    PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
    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;

    END IF;
    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 FOR SELECT * FROM EMP;
    OPEN V_CURSOR2 FOR SELECT * 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
    {
    public partial class WebForm4 : System.Web.UI.Page
    {
    string OracleConnectionString = ConfigurationManager.ConnectionStrings["scott"].ConnectionString;
    protected void 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 检索数据





    复制代码
    OracleConnection conn;
    using (conn = new OracleConnection(OracleConnectionString))
    {
    conn.Open();
    OracleCommand comm
    = new OracleCommand();
    comm.Connection
    = conn;
    comm.CommandType
    = CommandType.StoredProcedure;
    comm.CommandText
    = "curspkg.open_two_cursors";
    comm.Parameters.Add(
    new OracleParameter("empcursor", OracleType.Cursor)).Direction = ParameterDirection.Output;
    comm.Parameters.Add(
    new OracleParameter("deptcursor", OracleType.Cursor)).Direction = ParameterDirection.Output;

    OracleDataReader rdr
    = comm.ExecuteReader();
    GridView2.DataSource
    = rdr;
    GridView2.DataBind();
    rdr.NextResult();
    GridView3.DataSource
    = rdr;
    GridView3.DataBind();
    rdr.Close();
    }
  • 相关阅读:
    Vue数据双向绑定原理
    JS递归
    JS数据结构-链表
    JS数据结构-树
    React性能优化手段
    Django请求的生命周期
    Devops-git初识
    Django数据迁移的问题
    无监控,不运维!运维监控工具平台建设总结
    数据库-数据类型及主键外键
  • 原文地址:https://www.cnblogs.com/wangyt223/p/2742446.html
Copyright © 2011-2022 走看看