转自: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();
}
posted on 2012-10-27 14:21  王玉涛  阅读(345)  评论(0编辑  收藏  举报