test存储过程不进去(如何查看linux下的oracle存储过程)

seosqwseo4个月前 (09-17)测评日记48

一、oracle存储过程向DB2迁移

数据库迁移可以看作一个特殊的软件开发项目,与其他开发项目不同的是这个项目的需求是确定的,技术障碍较低,主要工作是代码编写和测试。对数据库管理人员来说,数据库数据迁移极具挑战性,一旦措施不当,珍贵的数据资源将面临丢失的危险,要成功地实现数据库数据平滑迁移,需要周密计划和充分准备,并按照一定的步骤来完成。另一方面,数据库迁移项目的成功也主要依赖于客户与开发商的积极配合和有序组织。当然,企业数据库通常数据量都比较大,结构也比较复杂,如果完全通过手工来完成,那是一个不可想象的大工程。所以正确的步骤加合适的迁移工具也能达到事半功倍的效果。

Oracle向DB2迁移一般来说遵循3大流程:迁移评估、模拟迁移、正式迁移。

全面的评估是迁移成功的一个关键要素,评估的总体目标是发现可能影响迁移过程的问题以便分配足够的资源来保证迁移取得成功。首先,是评估应用环境和应用程序,识别潜在的障碍;第二,您的 Oracle数据库将在多大程度上适应 DB2的硬数据;后,分析 Oracle数据库对象和过程,识别使用 DB2中不支持的那些特性的对象和过程。

1)在进行模拟迁移前,我们必须先设计数据迁移的方案,一般设计数据迁移方案主要包括以下几个方面工作:研究与数据迁移相关的资料,或在网站上查询相关内容、选择数据迁移的软硬件平台、选择数据迁移方法、选择数据备份和恢复策略、设计数据迁移和测试方案等。

2)根据设计的数据迁移方案,建立一个模拟的数据迁移环境,它既能仿真实际环境又不影响实际数据,然后在数据模拟迁移环境中测试数据迁移的效果。数据模拟迁移前也应按备份策略备份模拟数据,以便数据迁移后能按恢复策略进行恢复测试。

3)根据设计的数据迁移测试方案测试数据模拟迁移,也就是检查数据模拟迁移后数据和应用软件是否正常,主要包括:数据一致性测试、应用软件执行功能测试、性能测试、数据备份和恢复测试等。

数据模拟迁移测试成功后,可以正式实施数据的迁移了。在这里介绍一种简单的测试方法,首先利用 DB2兼容特性迁移 Oracle应用,创建兼容模式 DB2数据库。在 DB2 V9.7上启用 Oracle应用程序时,实例和数据库必须处于兼容模式。还建议调整舍入行为以匹配 Oracle。通过把重新验证语义(revalidation semantics)设置为 deferred_force,可以不按依赖次序部署对象。

$ db2set DB2_COMPATIBILITY_VECTOR=ORA

$ db2set DB2_DEFERRED_PREPARE_SEMANTICS=YES$ db2stop force

$ db2 create db testdb automatic storage yes on/db2data1,/db2data2,/db2data3 DBPATH ON/db2system PAGESIZE 32 K$ db2 update db cfg for testdb using auto_reval deferred_enforce$ db2 update db cfg for testdb using decflt_rounding round_half_upC:\> db2 update db cfg for testdb using decflt_rounding round_half_up在Windows上:

C:\> db2set DB2_COMPATIBILITY_VECTOR=ORA

C:\> db2set DB2_DEFERRED_PREPARE_SEMANTICS=YESC:\> db2stop force

C:\> db2 create db testdb automatic storage yes on C:,D: DBPATH ON E: PAGESIZE 32 KC:\> db2 update db cfg for testdb using auto_reval deferred_enforceC:\> db2 update db cfg for testdb using decflt_rounding round_half_up然后是将 Oracle数据库对象和数据迁移到 DB2。DB2 9.7提供的原生 Oracle PL/SQL和 Oracle SQL支持极大地简化了这一过程。现在我们先来看一个简单的示例,这个例子选自 Oracle来演示 PL/SQL中 CASE语句的使用,例子如下:

create or replace function Get_Grade3(score IN NUMBER) RETURN VARCHAR2 i**egin

use a Searched CASE Statement to find the Grade for thescore passed in as a parameter

WHEN score BETWEEN 80 AND 100 THEN return A;WHEN score BETWEEN 65 AND 79 THEN return B;WHEN score BETWEEN 50 AND 64 THEN return C;WHEN score BETWEEN 40 AND 49 THEN return D;WHEN score BETWEEN 0 AND 39 THEN return F;Comment the ELSE leg to generate the exceptionELSE return Invalid score;

return Exception- Case Not Found for score-|| score;end Get_Grade3;

select Get_Grade3(-1) from dual

C:\> db2 update db cfg for testdb using decflt_rounding round_half_up把这段代码保存在本地计算机的 D盘下面为 casetest.sql,在 DB2的 CLP plus中运行一下,居然一点都不需要修改就运行成功了,运行的结果如下:

Oracle向 DB2迁移:主要的流程与工具

这说明 DB2对 Oracle的兼容性的支持已经达到了一个很好的程度了。但是并不是所有程序都可以这么幸运的无需要修改就能正确的运行的。为了能够更好的完成迁移工作,还是需要了解两者之间特性的范围,以便我们能够更好的进行修改工作。在这里就不做说明了,大家可以去网上找找。

利用免费的 IBM DB2 Universal Database(UDB)Migration Toolkit(MTK)简化和改进向 DB2 UDB的迁移工作。这个新的迁移实用程序提供了向导和易于使用的五步界面,这些有助于您快速地将现有的 Sybase、 Microsoft SQL Server和Oracle数据库对象转换到 DB2通用数据库。使用 MTK,可以将数据类型、表、列、视图、索引、存储过程和触发器自动地转换成等价的 DB2数据库对象。MTK向数据库管理员(DBA)和应用程序程序员提供了使迁移任务自动化所需要的工具,而以前这些任务不但效率低下而且开销巨大。通过使用 MTK中的以下特性,您可以减少停机时间、消除人为错误,以及降低人工和与传统数据库迁移相关联的其它资源消耗。MTK可运行于 AIX、Linux、Solaris和 Windows*作系统上。

利用 DB2兼容特性和 IBM提供的免费数据迁移工具 Data Movement Tool,快速地将现有的 Oracle数据库对象转换到 DB2通用数据库。同时对应用中使用到的数据库访问语言以及接口进行转换,终实现整个应用系统的完整迁移。

3. IBM Optim Development Studio

IBM Optim Development Studio,它为 Oracle、DB2和 Informix提供一个集成的数据库开发环境。Optim Development Studio在开发和测试 SQL和 XQuery查询、存储过程、Web服务和 Java数据访问层方面将生产力提高了 50%,而且允许在不同或者相同的数据服务器中的数据对象包、存储过程、表、用户自定义函数、用户自定义类型、视图、模式等的**粘贴。

这三款工具都是来自于IBM官方的,大家有需要可以进去官方**。

以上只是简单的介绍了下迁移的流程和常用的工具,总的来说,迁移过程是一个复杂的过程,中间可能出现很多意想不到的情况,遇到问题,先查资料寻求解决方法,要有细心和耐心!我们在做迁移时,一定要做好备份,测试工作。而迁移工具只是一个辅助作用,如果单靠迁移工具是远远不够的。

二、如何查看linux下的oracle存储过程

1)在Linux系统中创建一个目录用来存放本*作需要用到的文件:

[root@dbserv~]# mkdir/sunjava

2)在Linux系统中将Java程序的ExcelOperate.class文件、poi.jar、ojdbc.jar放到sunjava目录下:

[root@dbserv~]# cp/home/oracle/ExcelOperate.class/sunjava

[root@dbserv~]# cp/home/oracle/poi.jar/sunjava

[root@dbserv~]# cp/home/oracle/jdbc.jar/sunjava

3)在Linux系统中配置Java相关环境变量:

用gedit打开配置文件profile文件:

[root@dbserv~]# gedit/etc/profile

在配置文件的后添加(或者存在的情况下修改)如下代码:

export J**A_HOME=/usr/java/ jdk1.6.0_32

exprot J**A_BIN=/usr/java/ jdk1.6.0_32/**n

export CLASSPATH=.:$J**A_HOME/lib/dt.jar:$J**A_HOME/lib/tools.jar:/sunjava/poi.jar:/sunjava/jdbc.jar/:/sunjava/

export PATH=$J**A_HOME/**n:$PATH

export J**A_HOME J**A_BIN CLASSPATH PATH

说明:在CLASSPATH增加了外部包所在的位置;好将.class文件所在的路径也添加进去。

4)将引用的外部包jar文件**到Oracle

的"$ORACLE_HOME/sqlj/lib"目录中:

[root@dbserv sunjava] cp jdbc.jar$ORACLE_HOME/sqlj/lib

4)进入Oracle的"$ORACLE_HOME/sqlj/lib"目录中,通过 loadjava命令,将调用的外部包放到Oracle数据库中:

loadjava-u sys/password-r-v-f-genmissing-s-grant public demo1.jar demo2.jar

loadjava-u sys/password-r-v-f-genmissing-s-grant public demo1.jar demo2.jar

[root@dbserv lib] loadjava-u apps/apps-r-v-f-genmissing-s-grant public poi.jar jdbc.jar

--创建数据库中的目录(将.class文件所在的物理目录映射到数据库中的目录)

CREATE OR REPLACE DIRECTORY test_dir AS'/sunjava';

(将需要调用的Java class文件映射到数据库中的Java Class)

CREATE OR REPLACE J**A CLASS USING BFILE(test_dir,'ExcelOperate.class');

SELECT a.OBJECT_NAME, a.OBJECT_TYPE,a.status FROM user_objects a WHERE a.OBJECT_NAME LIKE'%ExcelOperate%';

CREATE OR REPLACE PROCEDURE test_java AS LANGUAGE J**A

NAME'ExcelOperate.main(java.lang.String[])';

SET SERVEROUTPUT ON SIZE 5000;

CALL DBMS_J**A.SET_OUTPUT(5000);

三、如何用J**A调用存储过程

已储存过程储存在数据库中。对已储存过程的调用是 CallableStatement对象所含的内容。这种调用是用一种换码语法来写的,有两种形式:一种形式带结果参,另一种形式不带结果参数。结果参数是一种输出(OUT)参数,是已储存过程的返回值。两种形式都可带有数量可变的输入(IN参数)、输出(OUT参数)或输入和输出(INOUT参数)的参数。问号将用作参数的占位符。在JDBC中调用已储存过程的语法如下所示。注意,方括号表示其间的内容是可选项;方括号本身并不是语法的组成部份。{call过程名[(?,?,...)]}返回结果参数的过程的语法为:{?= call过程名[(?,?,...)]}不带参数的已储存过程的语法类似:{call过程名}通常,创建 CallableStatement对象的人应当知道所用的 DBMS是支持已储存过程的,并且知道这些过程都是些什么。然而,如果需要检查,多种DatabaseMetaData方法都可以提供这样的信息。例如,如果 DBMS支持已储存过程的调用,则supportsStoredProcedures方法将返回 true,而getProcedures方法将返回对已储存过程的描述。CallableStatement继承 Statement的方法(它们用于处理一般的 SQL语句),还继承了 PreparedStatement的方法(它们用于处理 IN参)。 CallableStatement中定义的所有方法都用于处理 OUT参数或 INOUT参数的输出部分:注册 OUT参数的 JDBC类型(一般 SQL类型)、从这些参数中检索结果,或者检查所返回的值是否为 JDBC NULL。 1、创建 CallableStatement对象 CallableStatement对象是用 Connection方法 prepareCall创建的。下例创建 CallableStatement的实例,其中含有对已储存过程 getTestData调用。该过程有两个变量,但不含结果参数:CallableStatement cstmt= con.prepareCall("{call getTestData(?,?)}");其中?占位符为IN、OUT还是INOUT参数,取决于已储存过程getTestData。 2、IN和OUT参数将IN参数传给 CallableStatement对象是通过 setXXX方法完成的。该方法继承自 PreparedStatement。所传入参数的类型决定了所用的setXXX方法(例如,用 setFloat来传入 float值等)。如果已储存过程返回 OUT参数,则在执行 CallableStatement对象以前必须先注册每个 OUT参数的 JDBC类型(这是必需的,因为某些 DBMS要求 JDBC类型)。注册 JDBC类型是用 registerOutParameter方法来完成的。语句执行完后,CallableStatement的 getXXX方法将取回参数值。正确的 getXXX方法是为各参数所注册的 JDBC类型所对应的 Java类型。换言之, registerOutParameter使用的是 JDBC类型(因此它与数据库返回的 JDBC类型匹配),而 getXXX将之转换为 Java类型。作为示例,下述代码先注册 OUT参数,执行由 cstmt所调用的已储存过程,然后检索在 OUT参数中返回的值。方法 getByte从第一个 OUT参数中取出一个 Java字节,而 getBigDecimal从第二个 OUT参数中取出一个 BigDecimal对象(小数点后面带三位数):CallableStatement cstmt= con.prepareCall("{call getTestData(?,?)}");

cstmt.registerOutParameter(1, java.sql.Types.TINYINT);

cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);

java.math.BigDecimal n= cstmt.getBigDecimal(2, 3); CallableStatement与 ResultSet不同,它不提供用增量方式检索大 OUT值的特殊机制。3、INOUT参数既支持输入又接受输出的参数(INOUT参数)除了调用 registerOutParameter方法外,还要求调用适当的 setXXX方法(该方法是从 PreparedStatement继承来的)。setXXX方法将参数值设置为输入参数,而 registerOutParameter方法将它的 JDBC类型注册为输出参数。setXXX方法提供一个 Java值,而驱动程序先把这个值转换为 JDBC值,然后将它送到数据库中。这种 IN值的 JDBC类型和提供给 registerOutParameter方法的 JDBC类型应该相同。然后,要检索输出值,就要用对应的 getXXX方法。例如,Java类型为byte的参数应该使用方法 setByte来赋输入值。应该给registerOutParameter提供类型为 TINYINT的 JDBC类型,同时应使用 getByte来检索输出值。下例假设有一个已储存过程 reviseTotal,其唯一参数是 INOUT参数。方法setByte把此参数设为 25,驱动程序将把它作为 JDBC TINYINT类型送到数据库中。接着,registerOutParameter将该参数注册为 JDBC TINYINT。执行完该已储存过程后,将返回一个新的 JDBC TINYINT值。方法 getByte将把这个新值作为 Java byte类型检索。CallableStatement cstmt= con.prepareCall("{call reviseTotal(?)}");

cstmt.registerOutParameter(1, java.sql.Types.TINYINT);

byte x= cstmt.getByte(1); 4、先检索结果,再检索 OUT参数由于某些 DBMS的限制,为了实现大的可移植性,建议先检索由执行CallableStatement对象所产生的结果,然后再用 CallableStatement.getXXX方法来检索 OUT参数。如果 CallableStatement对象返回多个 ResultSet对象(通过调用 execute方法),在检索 OUT参数前应先检索所有的结果。这种情况下,为确保对所有的结果都进行了访问,必须对 Statement方法 getResultSet、getUpdateCount和getMoreResults进行调用,直到不再有结果为止。检索完所有的结果后,就可用 CallableStatement.getXXX方法来检索 OUT参数中的值。 5、检索作为OUT参数的NULL值返回到 OUT参数中的值可能会是JDBC NULL。当出现这种情形时,将对 JDBC NULL值进行转换以使 getXXX方法所返回的值为 null、0或 false,这取决于getXXX方法类型。对于 ResultSet对象,要知道0或false是否源于JDBCNULL的唯一方法,是用方法wasNull进行检测。如果 getXXX方法读取的后一个值是 JDBC NULL,则该方法返回 true,否则返回 flase。

复杂的返回值关于存储过程的知识,很多人好像就熟悉我们所讨论的这些。如果这是存储过程的全部功能,那么存储过程就不是其它远程执行机制的替换方案了。存储过程的功能比这强大得多。

某些DBMS允许从存储过程中返回游标的一个引用。JDBC并不支持这个功能,但是Oracle、PostgreSQL和DB2的JDBC驱动器都支持在ResultSet上打开到游标的指针(pointer)。

设想列出所有没有活到退休年龄的诗人,下面是完成这个功能的存储过程,返回一个打开的游标,同样也使用PostgreSQL的pl/pgsql语言: create procedure list_early_deaths() return refcursor as'declare toesup refcursor;begin open toesup for SELECT poets.name, deaths.age FROM poets, deaths-- all entries in deaths are for poets.-- but the table might become generic. WHERE poets.id= deaths.mort_id AND deaths.age< 60; return toesup;end;' language'plpgsql';下面是调用该存储过程的Java方法,将结果输出到PrintWriter:

PrintWriter: static void sendEarlyDeaths(PrintWriter out){ Connection con= null; CallableStatement toesUp= null; try{ con= ConnectionPool.getConnection();// PostgreSQL needs a transaction to do this... con. setAutoCommit(false);// Setup the call. CallableStatement toesUp= connection.prepareCall("{?= call list_early_deaths()}"); toesUp.registerOutParameter(1, Types.OTHER); toesUp.execute(); ResultSet rs=(ResultSet) toesUp.getObject(1); while(rs.next()){ String name= rs.getString(1); int age= rs.getInt(2); out.println(name+" was"+ age+" years old.");} rs.close();} catch(SQLException e){// We should protect these calls. toesUp.close(); con.close();}}因为JDBC并不直接支持从存储过程中返回游标,我们使用Types.OTHER来指示存储过程的返回类型,然后调用getObject()方法并对返回值进行强制类型转换。

这个调用存储过程的Java方法是mapping的一个好例子。Mapping是对一个集上的*作进行抽象的方法。不是在这个过程上返回一个集,我们可以把*作传送进去执行。本例中,*作就是把ResultSet打印到一个输出流。这是一个值得举例的很常用的例子,下面是调用同一个存储过程的另外一个方法实现: public class ProcessPoetDeaths{ public abstract void sendDeath(String name, int age);} static void mapEarlyDeaths(ProcessPoetDeaths mapper){ Connection con= null; CallableStatement toesUp= null; try{ con= ConnectionPool.getConnection(); con.setAutoCommit(false); CallableStatement toesUp= connection.prepareCall("{?= call list_early_deaths()}"); toesUp.registerOutParameter(1, Types.OTHER); toesUp.execute(); ResultSet rs=(ResultSet) toesUp.getObject(1); while(rs.next()){ String name= rs.getString(1); int age= rs.getInt(2); mapper.sendDeath(name, age);} rs.close();} catch(SQLException e){// We should protect these calls. toesUp.close(); con.close();}}这允许在ResultSet数据上执行任意的处理,而不需要改变或者**获取ResultSet的方法: static void sendEarlyDeaths(final PrintWriter out){ ProcessPoetDeaths myMapper= new ProcessPoetDeaths(){ public void sendDeath(String name, int age){ out.println(name+" was"+ age+" years old.");}}; mapEarlyDeaths(myMapper);}这个方法使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths。该实例拥有sendDeath方法的一个实现,和我们上面的例子一样的方式把结果写入到输出流。当然,这个技巧并不是存储过程特有的,但是和存储过程中返回的ResultSet结合使用,是一个非常强大的工具。结论存储过程可以帮助你在代码中分离逻辑,这基本上总是有益的。这个分离的好处有:

快速创建应用,使用和应用一起改变和改善的数据库模式。

数据库模式可以在以后改变而不影响Java对象,当我们完成应用后,可以重新设计更好的模式。

存储过程通过更好的SQL嵌入使得复杂的SQL更容易理解。

编写存储过程比在Java中编写嵌入的SQL拥有更好的工具--大部分编辑器都提供语法高亮!

存储过程可以在任何SQL命令行中测试,这使得调试更加容易。并不是所有的数据库都支持存储过程,但是存在许多很棒的实现,包括免费/开源的和非免费的,所以移植并不是一个问题。Oracle、PostgreSQL和DB2都有类似的存储过程语言,并且有**的社区很好地支持。

存储过程工具很多,有像TOAD或TORA这样的编辑器、调试器和IDE,提供了编写、维护PL/SQL或pl/pgsql的强大的环境。

存储过程确实增加了你的代码的开销,但是它们和大多数的应用服务器相比,开销小得多。

相关文章

夏普(SHARP日本原装面板全面屏手机投屏智能语音HDR网络4K超高清液晶60|70英寸平板电视机质量好吗

夏普(SHARP日本原装面板全面屏手机投屏智能语音HDR网络4K超高清液晶60|70英寸平板电视机质量好吗

很多小伙伴在关注夏普(SHARP日本原装面板全面屏手机投屏智能语音HDR网络4K超高清液晶60|70英寸平板电视机怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使...

小米(MI)电视EA32英寸金属全面屏价格是多少

小米(MI)电视EA32英寸金属全面屏价格是多少

很多小伙伴在关注小米(MI)电视EA32英寸金属全面屏怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来...

绿联USB/Type-C读卡器3.0高速好不好用

绿联USB/Type-C读卡器3.0高速好不好用

很多小伙伴在关注绿联USB/Type-C读卡器3.0高速怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起...

小米积木质量好不好

小米积木质量好不好

很多小伙伴在关注小米积木怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来看看吧。...

掌阅iReaderLight2智能阅读本好不好

掌阅iReaderLight2智能阅读本好不好

很多小伙伴在关注掌阅iReaderLight2智能阅读本怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起...

ulanzi优篮子VL49怎么样?质量测评好不好用?

ulanzi优篮子VL49怎么样?质量测评好不好用?

很多小伙伴在关注ulanzi优篮子VL49怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来看看吧。...