Oracle 开发之 REFCURSOR.docx
- 文档编号:24294822
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:16
- 大小:20.83KB
Oracle 开发之 REFCURSOR.docx
《Oracle 开发之 REFCURSOR.docx》由会员分享,可在线阅读,更多相关《Oracle 开发之 REFCURSOR.docx(16页珍藏版)》请在冰豆网上搜索。
Oracle开发之REFCURSOR
前言
关于REF_CURSOR我们已经不再陌生,在前边的博客我们已经接触过了REF_CURSOR:
在博客《怎样让Oracle的存储过程返回结果集》中我们在一个返回结果集的HelloWorld级别的存储过程实例中用到了REF_CURSOR,在博客《烟草局绩效考核系统打分模块开发笔记》中我们在一个真实的项目中体会到REF_CURSOR给我们带来的神奇效果。
今天,我们将通过学习Oracle官方的这篇《Oracle开发之REF_CURSOR》进一步解开REF_CURSOR的神秘面纱,通过本文的学习,我们对REF_CURSOR的理解将会更加深入,而在以后的项目中对它的使用也必将更加规范。
正文
OracleREF_CURSOR简介
使用REF_CURSOR我们可以从存储过程中得到一个结果集对象。
REF_CURSOR分为两种基本类型:
强类型REF_CURSOR和弱类型REF_CURSOR,强类型REF_CURSOR返回的数据类型和长度在编译期就应该指明,而弱类型REF_CURSOR不需要。
强类型REF_CURSOR和Oracle9i之前的弱类型REF_CURSOR在包中应该这样定义:
viewplainprint?
1.createorreplacepackageREFCURSOR_PKGas
2.TYPEWEAK8i_REF_CURSORISREFCURSOR;
3.TYPESTRONG_REF_CURSORISREFCURSORRETURNEMP%ROWTYPE;
4.endREFCURSOR_PKG;
viewplaincopytoclipboardprint?
1.createorreplacepackageREFCURSOR_PKGas
2.TYPEWEAK8i_REF_CURSORISREFCURSOR;
3.TYPESTRONG_REF_CURSORISREFCURSORRETURNEMP%ROWTYPE;
4.endREFCURSOR_PKG;
返回REF_CURSOR的PL/SQL存储过程的编写示例:
viewplainprint?
1./**untilOracle9*/
2.createorreplaceproceduretest(p_deptnoINnumber
3.,p_cursorOUT
4.REFCURSOR_PKG.WEAK8i_REF_CURSOR)
5.is
6.begin
7.openp_cursorFOR
8.select*
9.fromemp
10.wheredeptno=p_deptno;
11.endtest;
viewplaincopytoclipboardprint?
1./**untilOracle9*/
2.createorreplaceproceduretest(p_deptnoINnumber
3.,p_cursorOUT
4.REFCURSOR_PKG.WEAK8i_REF_CURSOR)
5.is
6.begin
7.openp_cursorFOR
8.select*
9.fromemp
10.wheredeptno=p_deptno;
11.endtest;
Oracle9i之后,我们可以使用SYS_REFCURSOR作为REF_CURSOR的返回类型,例如:
viewplainprint?
1./**FromOracle9*/
2.createorreplaceproceduretest(p_deptnoINnumber
3.,p_cursorOUTSYS_REFCURSOR)
4.is
5.begin
6.openp_cursorFOR
7.select*
8.fromemp
9.wheredeptno=p_deptno;
10.endtest;
11.
12.
13./*Strongtype*/
14.
15.createorreplaceproceduretest(p_deptnoINnumber
16.,p_cursorOUTREFCURSOR_PKG.STRONG
17.REF_CURSOR)
18.is
19.begin
20.openp_cursorFOR
21.select*
22.fromemp
23.wheredeptno=p_deptno;
24.endtest;
viewplaincopytoclipboardprint?
1./**FromOracle9*/
2.createorreplaceproceduretest(p_deptnoINnumber
3.,p_cursorOUTSYS_REFCURSOR)
4.is
5.begin
6.openp_cursorFOR
7.select*
8.fromemp
9.wheredeptno=p_deptno;
10.endtest;
11.
12.
13./*Strongtype*/
14.
15.createorreplaceproceduretest(p_deptnoINnumber
16.,p_cursorOUTREFCURSOR_PKG.STRONG
17.REF_CURSOR)
18.is
19.begin
20.openp_cursorFOR
21.select*
22.fromemp
23.wheredeptno=p_deptno;
24.endtest;
JDBC对REF_CURSOR的调用
我们可以在JDBC中使用以下Java代码来得到REF_CURSOR:
viewplainprint?
1.publicvoidmethod()throwsSQLException{
2.Connectionconn=getConnection();
3.CallableStatementcstmt=null;
4.ResultSetrs=null;
5.intdeptno=10;
6.Objecttemp;
7.try{
8.cstmt=conn.prepareCall("begintest(?
?
);end;");
9.cstmt.setInt(1,deptno);
10.cstmt.registerOutParameter(2,OracleTypes.CURSOR);
11.cstmt.execute();
12.rs=(ResultSet)cstmt.getObject
(2);
13.ResultSetMetaDatarsm=rs.getMetaData();
14.intcolumnCount=rsm.getColumnCount();
15.while(rs.next()){
16.for(intj=0;j 17.temp=rs.getObject(j+1); 18.} 19.} 20.}finally{ 21.if(! rs==null){ 22.rs.close(); 23.} 24.if(! stmt==null){ 25.stmt.close(); 26.} 27.if(! conn==null){ 28.conn.close(); 29.} 30.} 31.} viewplaincopytoclipboardprint? 1.publicvoidmethod()throwsSQLException{ 2.Connectionconn=getConnection(); 3.CallableStatementcstmt=null; 4.ResultSetrs=null; 5.intdeptno=10; 6.Objecttemp; 7.try{ 8.cstmt=conn.prepareCall("begintest(? ? );end;"); 9.cstmt.setInt(1,deptno); 10.cstmt.registerOutParameter(2,OracleTypes.CURSOR); 11.cstmt.execute(); 12.rs=(ResultSet)cstmt.getObject (2); 13.ResultSetMetaDatarsm=rs.getMetaData(); 14.intcolumnCount=rsm.getColumnCount(); 15.while(rs.next()){ 16.for(intj=0;j 17.temp=rs.getObject(j+1); 18.} 19.} 20.}finally{ 21.if(! rs==null){ 22.rs.close(); 23.} 24.if(! stmt==null){ 25.stmt.close(); 26.} 27.if(! conn==null){ 28.conn.close(); 29.} 30.} 31.} PL/SQL中对REF_CURSOR的调用 viewplainprint? 1.createorreplaceproceduretest_callis 2.c_cursorREFCURSOR_PKG.STRONG_REF_CURSOR; 3.r_empc_emp%rowtype; 4.begin 5.test(10,c_cursor); 6.loop 7.fetchc_cursorintor_emp; 8.exitwhenc_cursor%notfound; 9.dbms_output.put_line(r_emp.name); 10.endloop; 11.closec_cursor; 12.endtest_call; viewplaincopytoclipboardprint? 1.createorreplaceproceduretest_callis 2.c_cursorREFCURSOR_PKG.STRONG_REF_CURSOR; 3.r_empc_emp%rowtype; 4.begin 5.test(10,c_cursor); 6.loop 7.fetchc_cursorintor_emp; 8.exitwhenc_cursor%notfound; 9.dbms_output.put_line(r_emp.name); 10.endloop; 11.closec_cursor; 12.endtest_call; 1,什么是REF游标? 动态关联结果集的临时对象。 即在运行的时候动态决定执行查询。 2,REF游标有什么作用? 实现在程序间传递结果集的功能,利用REFCURSOR也可以实现BULKSQL,从而提高SQL性能。 3,静态游标和REF游标的区别是什么? ①静态游标是静态定义,REF游标是动态关联; ②使用REF游标需REF游标变量。 ③REF游标能做为参数进行传递,而静态游标是不可能的。 4,什么是REF游标变量? REF游标变量是一种引用REF游标类型的变量,指向动态关联的结果集。 5,怎么使用REF游标? ①声明REF游标类型,确定REF游标类型; ⑴强类型REF游标: 指定retruntype,REF游标变量的类型必须和returntype一致。 语法: TypeREF游标名ISRefCursorReturn结果集返回记录类型; ⑵弱类型REF游标: 不指定returntype,能和任何类型的CURSOR变量匹配,用于获取任何结果集。 语法: TypeREF游标名ISRefCursor; ②声明Ref游标类型变量; 语法: 变量名已声明Ref游标类型; ③打开REF游标,关联结果集; 语法: OpenRef游标类型变量For查询语句返回结果集; ④获取记录,操作记录; 语法: FatchREF游标名InTo临时记录类型变量或属性类型变量列表; ⑤关闭游标,完全释放资源; 语法: CloseREF游标名; 例子: 强类型REF游标 Declare TypeMyRefCurAISREFCURSORRETURNemp%RowType; TypeMyRefCurBISREFCURSORRETURNemp.ename%Type; vRefCurAMyRefCurA; vRefCurBMyRefCurB; vTempAvRefCurA%RowType; vTempBvRefCurB.ename%Type; Begin OpenvRefCurAForSelect*fromempWhereSAL>2000; Loop FatchvRefCurAInTovTempA; ExitWhenvRefCurA%NotFound; DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||''||vTempA.eno||''||vTempA.ename||''||vTempA.sal) EndLoop; ClosevRefCurA; DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------'); OpenvRefCurBForSelectenamefromempWhereSAL>2000; Loop FatchvRefCurBInTovTempB; ExitWhenvRefCurB%NotFound; DBMS_OUTPUT.PUT_LINE(vRefCurB%RowCount||''||vTempB) EndLoop; ClosevRefCurB; DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------'); OpenvRefCurAForSelect*fromempWhereJOB='CLERK'; Loop FatchvRefCurAInTovTempA; ExitWhenvRefCurA%NotFound; DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||''||vTempA.eno||''||vTempA.ename||''||vTempA.sal) EndLoop; ClosevRefCurA; End; 例子: 弱类型REF游标 Declare TypeMyRefCurISRefCursor; vRefCurMyRefCur; vtempvRefCur%RowType; Begin Case(&n) When1ThenOpenvRefCurForSelect*fromemp; When2ThenOpenvRefCurForSelect*fromdept; Else OpenvRefCurForSelecteno,enamefromempWhereJOB='CLERK'; EndCase; ClosevRefCur; End; 6,怎样让REF游标作为参数传递? 这个是经过修改的,可以运行的程序: Declare TypeMyRefCurAISREFCURSOR; vRefCurAMyRefCurA; vRefCurBMyRefCurA; vTempAemp%RowType; vTempBemp.ename%Type; Begin OpenvRefCurAForSelect*fromempWhereSAL>2000; Loop FetchvRefCurAInTovTempA; ExitWhenvRefCurA%NotFound; DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||''||vTempA.empno||''||vTempA.ename||''||vTempA.sal); EndLoop; ClosevRefCurA; DBMS_OUTPUT.PUT_LINE('--------------------------------------'); OpenvRefCurBForSelectenamefromempWhereSAL>2000; Loop FetchvRefCurBInTovTempB; ExitWhenvRefCurB%NotFound; DBMS_OUTPUT.PUT_LINE(vRefCurB%RowCount||''||vTempB); EndLoop; ClosevRefCurB; DBMS_OUTPUT.PUT_LINE('---------------------------------------'); OpenvRefCurAForSelect*fromempWhereJOB='CLERK'; Loop FetchvRefCurAInTovTempA; ExitWhenvRefCurA%NotFound; DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||''||vTempA.empno||''||vTempA.ename||''||vTempA.sal); EndLoop; ClosevRefCurA; End; 2. 1.要执行返回REFCURSOR的存储过程,必须在OracleParameterCollection中定义参数,包括Cursor的OracleType以及Output的Direction。 数据提供程序只支持作为输出参数绑定REFCURSOR。 示例: REFCURSOR示例(使用OracleScott/Tiger架构中定义的表) 创建Oracle包和包正文 CREATEORREPLACEPACKAGECURSPKGAS TYPET_CURSORISREFCURSOR; PROCEDUREOPEN_ONE_CURSOR(N_EMPNOINNUMBER, IO_CURSORINOUTT_CURSOR); PROCEDUREOPEN_TWO_CURSORS(EMPCURSOROUTT_CURSOR, DEPTCURSOROUTT_CURSOR); ENDCURSPKG; / CREATEORREPLACEPACKAGEBODYCURSPKGAS PROCEDUREOPEN_ONE_CURSOR(N_EMPNOINNUMBER, IO_CURSORINOUTT_CURSOR) IS V_CURSORT_CURSOR; BEGIN IFN_EMPNO<>0 THEN OPENV_CURSORFOR SELECTEMP.EMPNO,EMP.ENAME,DEPT.DEPTNO,DEPT.DNAME FROMEMP,DEPT WHEREEMP.DEPTNO=DEPT.DEPTNO ANDEMP.EMPNO=N_EMPNO; ELSE OPENV_CURSORFOR SELECTEMP.EMPNO,EMP.ENAME,DEPT.DEPTNO,DEPT.DNAME FROMEMP,DEPT WHEREEMP.DEPTNO=DEPT.DEPTNO; ENDIF; IO_CURSOR: =V_CURSOR; ENDOPEN_ONE_CURSOR; PROCEDUREOPEN_TWO_CURSORS(EMPCURSOROUTT_CURSOR, DEPTCURSOROUTT_CURSOR) IS V_CURSOR1T_CURSOR; V_CURSOR2T_CURSOR; BEGIN OPENV_CURSOR1FORSELECT*FROMEMP; OPENV_CURSOR2FORSELECT*FROMDEPT; EMPCURSOR: =V_CURSOR1; DEPTCURSOR: =V_CURSOR2; ENDOPEN_TWO_CURSORS; ENDCURSPKG; / 示例: OracleDataReader中的REFCURSOR参数 usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Web; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; usingSystem.Configuration; usingSystem.Data; using
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Oracle 开发之 REFCURSOR 开发