《PL/SQL 语言开发参考手册》下载地址
前言
关于 REF_CURSOR 我们已经不再陌生,在前边的博客我们已经接触过了 REF_CURSOR:在博客《怎样让 Oracle 的存储过程返回结果集》中我们在一个返回结果集的 Hello World 级别的存储过程实例中用到了 REF_CURSOR,在博客《烟草局绩效考核系统打分模块开发笔记》中我们在一个真实的项目中体会到 REF_CURSOR 给我们带来的神奇效果。今天,我们将通过学习 Oracle 官方的这篇《Oracle 开发之 REF_CURSOR》进一步解开 REF_CURSOR 的神秘面纱,通过本文的学习,我们对 REF_CURSOR 的理解将会更加深入,而在以后的项目中对它的使用也必将更加规范。
正文
Oracle REF_CURSOR 简介
使用 REF_CURSOR 我们可以从存储过程中得到一个结果集对象。
REF_CURSOR 分为两种基本类型:强类型 REF_CURSOR 和弱类型 REF_CURSOR,强类型 REF_CURSOR 返回的数据类型和长度在编译期就应该指明,而弱类型 REF_CURSOR 不需要。
强类型 REF_CURSOR 和 Oracle 9i 之前的弱类型 REF_CURSOR 在包中应该这样定义:
- create or replace package REFCURSOR_PKG as
- TYPE WEAK8i_REF_CURSOR IS REF CURSOR;
- TYPE STRONG_REF_CURSOR IS REF CURSOR RETURN EMP%ROWTYPE;
- end REFCURSOR_PKG;
返回 REF_CURSOR 的 PL/SQL 存储过程的编写示例:
- /** until Oracle 9 */
- create or replace procedure test( p_deptno IN number
- , p_cursor OUT
- REFCURSOR_PKG.WEAK8i_REF_CURSOR)
- is
- begin
- open p_cursor FOR
- select *
- from emp
- where deptno = p_deptno;
- end test;
Oracle 9i 之后,我们可以使用 SYS_REFCURSOR 作为 REF_CURSOR 的返回类型,例如:
- /** From Oracle 9 */
- create or replace procedure test( p_deptno IN number
- , p_cursor OUT SYS_REFCURSOR)
- is
- begin
- open p_cursor FOR
- select *
- from emp
- where deptno = p_deptno;
- end test;
- /* Strong type */
- create or replace procedure test( p_deptno IN number
- , p_cursor OUT REFCURSOR_PKG.STRONG
- REF_CURSOR)
- is
- begin
- open p_cursor FOR
- select *
- from emp
- where deptno = p_deptno;
- end test;
JDBC 对 REF_CURSOR 的调用
我们可以在 JDBC 中使用以下 Java 代码来得到 REF_CURSOR:
- public void method() throws SQLException{
- Connection conn = getConnection();
- CallableStatement cstmt = null;
- ResultSet rs = null;
- int deptno = 10;
- Object temp;
- try{
- cstmt = conn.prepareCall("begin test(?,?); end;");
- cstmt.setInt(1, deptno);
- cstmt.registerOutParameter(2, OracleTypes.CURSOR);
- cstmt.execute();
- rs = (ResultSet) cstmt.getObject(2);
- ResultSetMetaData rsm = rs.getMetaData();
- int columnCount = rsm.getColumnCount();
- while (rs.next()){
- for (int j=0;j< columnCount;j++){
- temp = rs.getObject(j+1);
- }
- }
- } finally {
- if (!rs==null){
- rs.close();
- }
- if (!stmt==null){
- stmt.close();
- }
- if (!conn==null){
- conn.close();
- }
- }
- }
PL/SQL 中对 REF_CURSOR 的调用
- create or replace procedure test_call is
- c_cursor REFCURSOR_PKG.STRONG_REF_CURSOR;
- r_emp c_emp%rowtype;
- begin
- test(10,c_cursor);
- loop
- fetch c_cursor into r_emp;
- exit when c_cursor%notfound;
- dbms_output.put_line(r_emp.name);
- end loop;
- close c_cursor;
- end test_call;