`

Oracle集合类型输出参数的PL/SQL存储过程及其Java调用

 
阅读更多

一、引用文章

现在的java的数据库-关系映射技术似乎不提倡用存储过程,其实存储过程更能发挥数据库的效率。
1  引言
存储过程因其执行效率高、与事务处理的结合、运行更安全等优点,在数据库应用程序中被广泛采用。PL/SQL是用于从各种环境中访问Oracle数据库的一种编程语言,它与数据库服务器集成在一起,PL/SQL编写的存储过程编译效率高,网络系统开销小,同时PL/SQL直观性好,是大多数人的选择。
NumberVarchar等基本标量类型为输出参数的PL/SQL存 储过程,每个输出参数只能返回一个对应值。而在实际数据库应用程序中,尤其是在进行系统综合查询统计时,往往需要返回二维数组或结果集,这时应考虑在存储 过程中使用集合这种数据结构。对于集合,我们可以一次把许多元素作为一个整体进行操作,也可以对集合中的单个元素进行操作,使用方便、灵活。
 
2  PL/SQL存储过程及Java程序的编写
2.1  索引表作为输出参数

索引表是无约束的,其大小的唯一限制(除可用内存外)就是它的关键字BINARY_INTEGER类型所能表示数值的约束(-2147483647...+2147483647),其元素不需要按任何特定顺序排列。在声明时,我们不需要指定其大小,而且对索引表的元素可以直接赋值,不用初始化,可见使用索引表极其方便。

2.1.1存储过程的编写
我们可以在PL/SQL语句块中定义索引表,但作为输出参数的索引表,必须要在包(package)里定义,方法如下:
create or replace package out_param is                                        
---- 定义了元素是varchar2类型的一个索引表类型
type out_index_table_typ is table of varchar2(50) index by binary_integer;
end out_param;
接下来就可以在pl/sql存储过程里引用在包里定义的索引表类型:
                   create or replace procedure testPro1(in_param in varchar2,o_table out  out_param. out_index_table_typ ) is
                      begin
                          -------这里略去程序体
                      end  testPro1;
          其中,返回的索引表类型前必须用包名加上句点来引用out_param. out_index_table_typ
2.1.2  Java程序的编写
索引表与数据库表很形似,有keyvalue两列,但它不是真正的数据库表,不可以存储到数据库中。因此索引表不能使用SQL进行操作,这样它的内容不能通过一个标准的SELECT语句返回游标得到。这一点与嵌套表有很大不同。由存储过程返回的索引表可以映射成java数组类型、JDBC DatatypesBigDecimal[]数组类型和oracleDatum[]数组。有一点要注意,尽管索引表中的元素不一定要按任何特定顺序排列,其元素可以借助于任意有效关键字而插入,但对映射数组元素的引用应该从1开始,而且要连续,否则映射成数组时会出现null元素。
下面示例为将索引表映射成java数组类型。

Java代码  收藏代码
  1. import oracle.jdbc.*;  
  2. import oracle.sql.*;  
  3. import java.sql.*;  
  4. public class ReturnIndexTable  
  5. {  Connection ociconn=null;  
  6. OracleCallableStatement stmt =null;  
  7. public String[] getTable(String in_param)  
  8. {  String[] reAry=null;  
  9. try  
  10. {  OracleDriver S_Driver=null;  
  11. if(S_Driver==null)  
  12. S_Driver=new oracle.jdbc.OracleDriver();  
  13. DriverManager.registerDriver(S_Driver);  
  14. String url="jdbc:oracle:oci8:@test";  
  15. String user="user";  
  16. String password=" password";  
  17. ociconn= DriverManager.getConnection(url,user,password);  
  18. stmt =(OracleCallableStatement)ociconn.prepareCall("begin testPro1(?,?); end;");  
  19. // 返回的索引表最大长度(可以大于索引表实际长度)  
  20. int  maxLen =31;  
  21. // 索引表元素类型  
  22. int  elemSqlType = OracleTypes.VARCHAR;  
  23. //索引表元素长度(CHAR, VARCHAR or RAW),其它元素类型可忽略该项值,但该参数仍须定义  
  24. int  elemMaxLen=50;  
  25. stmt.setString(1,in_param);  
  26. // 注册返回参数  
  27. stmt.registerIndexTableOutParameter(2,maxLen,elemSqlType,elemMaxLen);  
  28. stmt.execute();  
  29. // 返回数组类型  
  30. reAry=(String[])stmt.getPlsqlIndexTable(2);  
  31. }  
  32. catch (Exception e)  
  33. {e.printStackTrace();  
  34. }  
  35. finally  
  36. {return reAry;  
  37. }  
  38. }  
  39. //关闭连接.............  
  40. }  

 2.2  可变数组作为输出参数

          可变数组和另外两种集合类型不同,其元素在内存中是连续存储的,且在大小方面有一个固定的上界。声明时需要指定该数组中元素的最大数目(可变数组的大小可以用EXTEND方法来增加,但不能被扩展超过所声明的极限大小)。

可变数组的元素被赋值之前,必须使用构造器进行初始化。元素插入数组时应从索引1开始,连续插入。
2.2.1 存储过程的编写
可变数组的定义方法如下:
create or replace type testArray is varray(5) of number(3)
         PL/SQL存储过程里调用可变数组作为输出参数:
create or replace function getTestArray return testArray
as
   o_data testArray:= testArray ();  
begin
    for v_count in 1..5 loop
      o_data.extend;
      o_data(v_count):= v_count;
    end loop;
   return o_data;
end;
2.2.2  Java程序的编写
        由存储过程返回的可变数组同样可以映射成java数组类型。但Java程序调用存储过程返回的可变数组方式和索引表方式却不相同,这一点应注意,具体方法如下:
public static void main( )
{
......
//调用存储过程
.           OracleCallableStatement stmt =(OracleCallableStatement)conn.prepareCall ( "begin ? := getTestArray; end;" );   
            stmt.registerOutParameter( 1, OracleTypes.ARRAY," testArray" );
            stmt.executeUpdate();
            // 得到 ARRAY 对象
            ARRAY simpleArray = stmt.getARRAY(1);
//转换为java数组
            String[ ] values = (String[])simpleArray.getArray();
//输出数组内容
            for( int i = 0; i < values.length; i++ )
             System.out.println( "row " + i + " = '" + values[i] +"'" );
}
2.3  嵌套表作为输出参数
存 储过程中使用嵌套表,并不是直接将嵌套表作为输出参数,而是对嵌套表"造型"后以游标形式输出。嵌套表的基本功能与索引表相同,但嵌套表可以使用SQL进 行操作,其内容可通过SELECT 语句查询并"造型"后以游标形式返回。在大多数的查询统计中,常常需要返回结果集,这时使用嵌套表就尤其方便。笔者在开发过程中深刻体会到使用对象嵌套表 可以解决绝大多数的查询统计问题。下面着重介绍如何在存储过程里利用对象类型的嵌套表。
对于任意的统计分析表格,我们可以将其简化成下面的输出形式:

  
      统计项目1
统计项目2
统计项目3
统计项目4
名称1
 
 
 
 
名称2
 
 
 
 

这样我们把每一行看作是一个对象实例,该行的每一列则可以看作是该对象的一个属性,下面通过构造对象,然后对包含对象的嵌套表进行造型,返回游标得到结果集。
 2.3.1 存储过程的编写
  首先构造统计对象如下:
      create or replace type TestObj as object
(
 vname  varchar2(20),    --名称
 item1   number,        --统计项目1
 item2   number,        --统计项目2
 item3   number,        --统计项目3
item4   number        --统计项目4
);
构造包含对象类型的嵌套表:
 create or replace type TestNestTable as table of TestObj;
定义对索引表"造型"后的输出的游标类型:
create or replace package out_param is
type out_cur is ref cursor;        
下面是嵌套表作为输出参数的存储过程:
create or replace procedure testPro2(o_cur out out_param.out_cur ) is
---- 包含对象的嵌套表变量的声明
v_objTable  TestNestTable= TestNestTable ();
begin
                     --嵌套表变量的使用
v_objTabl.extend;
v_objTable(1):= TestObj(‘张三',1212312334);
v_objTabl.extend;
v_objTable(2):= TestObj(‘李四,22223223234);
--对嵌套表进行"造型"返回游标
open  o_cur  for  select * from Table(cast (v_objTable as TestNestTable) );
end  testPro2;
2.3.2  Java程序的编写
    //从游标返回结果集
public ResultSet getCursor()
{
try
{
......
stmt =(CallableStatement )conn.prepareCall("call testPro2(?)");
//注册游标对象类型
stmt.registerOutParameter(1,OracleTypes.CURSOR);
stmt.execute();
//返回结果集
ResultSet  Rs=(ResultSet)stmt.getObject(1);
}
catch(Exception e)
{
}
return Rs;
}
结束语
使用索引表和可变数组,可将返回的集合映射成Java数组。由于索引表会自动分配空间,在声明时不需要指定其大小,而且不需要初始化,使用起来比较方便。但是索引表作为输出参数只能使用oci驱动(返回游标时,可以用瘦客户驱动也可以用oci驱动),所需要的动态连接库文件(ocijdbc9.dll)要在环境变量里进行设置(例如:path=D:\oracle\ora90\BIN),在不同的环境下OCI驱动还可能出现类装载异常,所以返回索引表尽管方便,但偶尔会出现意想不到的错误。可变数组映射成Java数组简单,对于返回小数据量的结果,也是不错的选择,但使用可变数组作为输出参数,声明时必须限定该数组的大小上限,并且需使用构造器初始化。
使用嵌套表,可以对嵌套表进行SQL操作,其内容能通过对标准的SELECT 语句造型后可转化为游标输出。而且嵌套表的内容相当于session变量,当断开连接后即释放内存,但同样存在需要初始化和扩展的问题。
综 上所述,究竟采用索引表、嵌套表和可变数组中哪一种作为存储过程的输出要看具体的要求和开发环境。有一点我们需要注意,如果返回的数据量较大,以数组形式 返回,则需一次性取回所有结果,在PL/SQL里为所有结果分配空间并复制,然后将这些数据通过网络发送到客户端,客户端也同样需要分配空间接受这些数 据;而采用游标形式,只要返回一个指针,然后分批返回结果(可自定义每次返回记录的条数),而不是一次性返回所有结果,因此在客户端不需分配大块的空间存 放所有结果。可见,对于大数据量的应用程序,返回游标程序运行效率会更高。

 

二、测试示例JAVA

public static void testPro2() {
        Connection conn = DBUtil.getConnection();
        CallableStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt =(CallableStatement)conn.prepareCall("call testPro2(?)");
            //注册游标对象类型
            stmt.registerOutParameter(1, OracleTypes.CURSOR);
            stmt.execute();
            //返回结果集
            rs =(ResultSet)stmt.getObject(1);
            while (rs.next()) {
                //
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (stmt != null)
                    stmt.close();
            } catch (Exception se) {
            }
            DBUtil.closeConnection(conn);
        }
    }

 

三、SQL代码

create or replace package out_param is
  type out_cur is ref cursor;
end out_param;

 

create or replace type TestNestTable as table of TestObj

 

create or replace procedure testPro2(o_cur out out_param.out_cur) is
  ---- 包含对象的嵌套表变量的声明
  v_objTable TestNestTable := TestNestTable();
begin
  --嵌套表变量的使用
  v_objTable.extend;
  v_objTable(1) := TestObj('张三', 12, 123, 123, 34);
  v_objTable.extend;
  v_objTable(2) := TestObj('李四', 22, 223, 223, 234);
  --对嵌套表进行"造型"返回游标
  open o_cur for
    select * from Table(cast(v_objTable as TestNestTable));
end testPro2;

 

分享到:
评论

相关推荐

    oracle10g_pl/sql

    Oracle 10g PL/SQL 是Oracle数据库系统中用于创建和管理存储过程、函数、触发器等数据库对象的编程语言。本教程旨在为初学者提供一个全面的学习平台,同时也为经验丰富的开发者提供参考资料。PL/SQL是Oracle特有的...

    Oracle集合类型输出参数的PLSQL存储过程及其Java调用.docx

    ### Oracle集合类型输出参数的PL/SQL存储过程及其Java调用 #### 1. 引言 存储过程因其高效执行、事务处理能力以及安全性,在数据库应用程序中被广泛应用。特别是使用Oracle数据库时,PL/SQL(一种专为Oracle设计的...

    Oracle集合类型输出参数的PLSQL存储过程及其Java调用.doc

    Oracle集合类型输出参数的PL/SQL存储过程及Java调用主要涉及如何在Oracle数据库中使用存储过程处理集合数据,并在Java应用中调用这些过程。本文档介绍了一种使用索引表作为输出参数的方法,以及如何在Java中处理返回...

    ORACLE PL/SQL从入门到精通

    ORACLE PL/SQL是从入门到精通的专业知识,涵盖了数据库开发与管理的多个方面,包括触发器、过程、函数、软件包、异常处理、游标、循环、分支、变量使用、数据库安装等关键知识点。 触发器是数据库中用来保证数据...

    oracle 9i pl/sql程序设计笔记

    **标题与描述**:本文档围绕“Oracle 9i PL/SQL程序设计笔记”这一核心主题,深入探讨了PL/SQL语言的基础知识及其在Oracle 9i数据库环境中的应用。 **关键词**:Oracle 9i、PL/SQL #### PL/SQL程序结构详解 **2.1...

    Oracle Database 12c PL/SQL开发指南 实例源代码

    14. **PL/SQL与Java集成**:通过PL/SQL调用Java存储过程,实现两种技术的融合。 通过"Oracle Database 12c PL/SQL开发指南"中的实例源代码,读者可以亲手实践上述各种概念和技术,从而更深入地理解和掌握PL/SQL的...

    oracle_oracle_oraclepl/sql_

    Oracle PL/SQL是一种强大的编程语言,它结合了SQL(结构化查询语言)的数据库操作能力和过程性编程语言的控制结构。在"Oracle PL/SQL"这本书中,作者深入浅出地探讨了这一语言的核心概念和实用技巧,尤其适合法语...

    Oracle PL/SQL程序设计(第5版)(上下册)

    - **PL/SQL简介**:PL/SQL(Procedural Language for SQL)是Oracle数据库的一种内嵌式过程化语言,用于增强SQL的功能。它允许在SQL查询的基础上添加控制流语句、变量定义、错误处理等特性。 - **环境搭建与配置**:...

    oracle pl/sql从入门到精通 配套源代码

    2. **存储过程和函数**:这些是PL/SQL的核心组成部分,它们封装了一系列操作,可以被多次调用,提高代码复用性。书中可能包含各种示例,如自定义计算函数、处理业务逻辑的存储过程等。 3. **触发器**:当数据库中的...

    oracle 中 pl/sql 只是学习方法

    4. **存储过程和函数**:存储过程是一组预先编译的PL/SQL语句,可以在需要时调用,减少网络通信,提高性能。函数与存储过程类似,但必须返回一个值。它们可以用于封装复杂的业务逻辑,增强代码复用性。 5. **异常...

    pl/sql最新中文手册

    11. **PL/SQL与Java、C等其他语言的互操作性**:Oracle提供了与多种编程语言接口的机制,手册会讲解如何在PL/SQL中调用外部程序或被其他程序调用。 12. **调试和错误诊断**:最后,手册会介绍如何使用Oracle提供的...

    Oracle PL/SQL学习官方教材

    Oracle PL/SQL是一种强大的编程语言,它将SQL与过程编程语言的特性相结合,为数据库开发提供了丰富的功能。在Oracle数据库环境中,PL/SQL是开发高效、可靠和可维护的数据库应用程序的关键工具。以下是对"Oracle PL/...

    一个对数据库的操作工具PL/SQLpl/sqL工具

    PL/SQL是Oracle公司开发的一种过程化语言,全称为Procedural Language/Structured Query Language,它是SQL的一个扩展,专门用于处理Oracle数据库系统。这个“PL/SQL工具”显然是一个用于辅助管理和操作Oracle数据库...

    Oracle PL/SQL专家指南-高级PL/SQL解决方案的设计与开发

    《Oracle PL/SQL专家指南-高级PL/SQL解决方案的设计与开发》是一本深入探讨Oracle数据库中的PL/SQL编程的专业书籍。PL/SQL是Oracle数据库特有的编程语言,它结合了SQL的查询能力与过程式编程语言的功能,使得数据库...

    Oracle PL/SQL 实例精解(第4版涵盖Oracle 11g)+源码脚本

    PL/SQL是Oracle数据库中用于创建存储过程、函数、触发器、包等数据库对象的主要工具。第4版特别关注了在Oracle 11g环境下的新特性,如性能优化、错误处理和并发控制等。 1. **基础语法**:PL/SQL的基础包括声明变量...

    oracle PL/SQL测试题目和详细答案

    以上知识点涵盖了Oracle PL/SQL的基础知识,包括存储过程、函数、触发器、数据类型、动态SQL、索引类型、约束等关键概念及其应用方法。通过理解和掌握这些知识点,可以帮助开发者更好地进行数据库设计和开发工作。

    oracle pl/sql fundamentals

    Oracle PL/SQL Fundamentals是Oracle University为学生设计的一份培训指南,旨在深入理解并掌握Oracle数据库中的PL/SQL编程基础。PL/SQL是Oracle数据库特有的结构化查询语言扩展,它结合了SQL的强大功能与过程性编程...

    Oracle资料学习PL/SQL必备

    7. **存储过程和函数**:存储过程是一组可重用的PL/SQL代码,可以在数据库中保存并按需调用,而函数则返回一个值。它们可以接受参数,提高代码复用性和性能。 8. **触发器**:触发器是在特定数据库事件(如INSERT、...

    pl/sql developer11.0

    PL/SQL Developer是一款由Allround Automations公司开发的专业Oracle数据库开发工具,专为编写、调试、测试和管理PL/SQL代码而设计。标题中的“pl/sql developer11.0”指的是该软件的第11个主要版本。在本文中,我们...

    oracle 经典资料及PL/SQL 使用指南 英文版

    这篇“Oracle经典资料及PL/SQL使用指南”的英文版,将帮助学习者深入理解Oracle数据库的基础概念以及PL/SQL的高级用法。 一、Oracle数据库基础 1. 数据库架构:Oracle数据库采用多层架构,包括物理存储层、逻辑...

Global site tag (gtag.js) - Google Analytics