您的位置:首页 > 数据库 > Oracle

oracle 游标变量REF Cursor

2016-06-16 16:46 501 查看
转自: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 中定义参数,包括Cursor 的 OracleType 以及 Output 的 Direction。 数据提供程序只支持作为输出参数绑定 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();
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: