内容


解决 DB2 UDB Java 存储过程的常见问题

Comments

简介

在数据库应用程序中使用存储过程有许多好处,包括减少对网络的使用、提高性能以及降低开发成本。Java 存储过程是 DB2 支持的最流行的例程之一。原因之一是,由于 Java 编程语言非常流行,所以 Java 开发人员非常多。因此,在有多种语言可供选择时,Java 例程往往是首选的。

DB2 存储过程不一定非用 Java 来编写。如果业务逻辑只需要简单的存储过程,那么可以考虑用 SQL Procedure Language(SQL PL)进行存储过程开发。SQL 存储过程总是作为 受信任的 存储过程运行,并且因为它们不依赖于外部 Java 虚拟机(Java Virtual Machine,JVM)进程来装载过程,所以比 Java 例程快。

使用 Java 存储过程的好处与创建 Java 应用程序时获得的好处相同。Java 是非常安全的编程语言。用户只能获得 Java 字节码。Java 代码编译一次,就能够在支持 JVM 的任何计算机和操作系统上运行。因为 Java 代码在单独的 JVM 中运行,所以 JVM 能够正确地处理(可能导致 JVM 崩溃的)危险操作。不需要实现单独的基础设施来处理危险状况,因为 Java 具有捕获异常的内置机制。

在本文中,我们有时将 Java 存储过程称为例程。在 DB2 UDB 中存储过程和例程是同义的。在 DB2 V8 中引入了例程的概念,它既表示存储过程,也表示用户定义函数(UDF)。

本文讨论在开发或运行 Java 存储过程的过程中可能遇到的常见错误消息。在开始讨论之前,我们先讨论 Java 存储过程开发的重要概念和配置参数。接下来,描述如何启用 DB2 Java。需要建立 Java 环境才能成功地调用 Java 存储过程。

关键概念

以下概念对于理解存储过程在 DB2 环境中如何工作非常重要:

  • FENCED 或 NOT FENCED: 这个子句指定例程是否被认为可以在数据库管理器操作环境的进程或地址空间中“安全地”运行。

    如果存储过程被注册为 FENCED,那么数据库管理器就禁止过程访问它的内部资源(比如数据缓冲区)。大多数例程都有作为 FENCED 或 NOT FENCED 运行的选项。但是,Java 例程只能注册为 FENCED。一般来说,作为 FENCED 运行的例程执行得没有作为 NOT FENCED 运行的相似例程那么快。这是因为 NOT FENCED 例程可以在数据库引擎内利用进程间通信(IPC)。

    对没有经过彻底测试的例程使用 NOT FENCED,可能会破坏 DB2 完整性。DB2 对于许多常见的意外故障类型采取了某些保护措施,但是在使用 NOT FENCED 例程时无法保证完全的完整性。NOT FENCED 例程常常被称为受信任的(trusted)。声明为受信任的例程在数据库管理器的地址空间中运行。

    将例程注册为 NOT FENCED 需要 SYSADM 特权、DBADM 特权或一个特殊的特权(CREATE_NOT_FENCED)。定义为 NOT THREADSAFE 的例程只能指定 FENCED。

  • THREADSAFE 或 NOT THREADSAFE: 这个子句指定这个例程是否可以安全地在其他例程的进程中执行(THREADSAFE 是可以,NOT THREADSAFE 是不可以)。

    如果过程定义为 THREADSAFE,数据库管理器就可以在其他例程的进程中调用这个过程。一般来说,要想定义为 THREADSAFE,例程不应该使用任何全局或静态数据区域。许多编程参考资料讨论了如何编写线程安全的例程。FENCED 和 NOT FENCED 过程都可以是 THREADSAFE 的。

    如果过程定义为 NOT THREADSAFE,数据库管理器就绝不会在其他例程的进程中调用这个过程。

    在 Java 存储过程中,THREADSAFE 是默认的,无论它被声明为 FENCED 还是 NOT FENCED 存储过程。

配置参数

DB2 有许多配置参数。一些参数在数据库级上定义,其他参数在数据库管理级上定义。影响存储过程行为的大多数参数是在实例级(即数据库管理级)上定义的。

  • KEEPFENCED: 这是一个数据库管理器配置(DBM CFG)参数。在以前的 DB2 UDB 版本中,它被称为 KEEPDARI。这个参数指出,在完成一个防护模式例程调用之后,是否保留防护模式进程(db2fmp)。防护模式进程是作为单独的系统实体创建的,以便将用户编写的防护模式代码与数据库管理器代理进程隔离开来。这个参数只能应用于数据库服务器。在开发存储过程时,强烈建议将这个参数设置为 NO,这样,调用存储过程时总会得到全新的存储过程副本。如果存储过程常常重新编译,那么这特别重要。在生产环境中,应该将这个参数设置为 YES,因为它会显著地影响性能。NOT FENCED 存储过程不受这个配置参数影响,因为它们不在 db2fmp 进程中运行。
  • FENCED_POOL: 这是一个数据库管理器配置(DBM CFG)参数。它代表系统上缓存的空闲防护模式进程(db2fmp)的数量。对于线程化的 db2fmp 进程(为线程安全的存储过程和 UDF 提供服务的进程),这个参数代表每个 db2fmp 进程中缓存的线程数量。对于非线程化的 db2fmp 进程,这个参数代表缓存的进程数量。
  • NUM_INITFENCED: 这是一个数据库管理器配置(DBM CFG)参数。这个参数表示在 DB2START 时在 db2fmp 池中创建的非线程化空闲 db2fmp 进程的初始数量。如果没有指定 KEEPFENCED,这个参数就被忽略。
  • JDK_PATH: 这是一个数据库管理器配置(DBM CFG)参数。这个参数指出用来执行 Java 存储过程的 JVM 或 Java Development Kit(JDK)的位置。这是一个非常重要的参数。它的值应该设置为包含 JVM Java 可执行文件的 “bin” 目录的上一级目录的完整路径。在 Windows® 平台上的一个例子是 C:\Program Files\IBM\SQLLIB\java\jdk。UNIX® 例子是 /usr/java1.3.1。JVM 级别也非常重要,因为根据使用的 db2level 和平台级别,DB2 UDB 只支持某些 JVM 级别。(这个问题将在本文稍后讨论。)
  • JAVA_HEAP_SZ: 这是一个数据库管理器配置(DBM CFG)参数。这个参数决定为 Java 存储过程和 UDF 服务的 Java 解释器所使用的堆的最大大小。为了避免在 Java 存储过程中耗尽内存,可以增加这个值。但是,如果在环境中要调用许多存储过程(即,每个 JVM 都会分配这么多堆空间),那么分配太多内存也是有害的。一般规则是保持 JAVA_HEAP_SZ 为默认设置,即 512(4K 页)。
  • ASLHEAPSZ: 这是一个数据库管理器配置(DBM CFG)参数。应用程序支持层堆是本地应用程序和与它相关联的代理之间的通信缓冲区。这个缓冲区作为每个数据库管理器代理共享的内存分配。这个参数确定缓冲区的大小,用于在例程和发出调用的应用程序之间传递参数。存储过程中的参数数量和参数大小明确地影响这个配置参数。系统上允许同时存在的 db2fmp 进程的最大数量也受这个参数的影响。
  • QUERY_HEAP_SZ: 这是一个数据库管理器配置(DBM CFG)参数。这个参数指定可以分配给查询堆的最大内存量。查询堆用于在代理的私有内存中存储每个查询。每个查询的信息包括输入和输出 SQLDA、语句文本、SQLCA、包名、创建者、区号和一致性符号。提供这个参数是为了确保应用程序不会不必要地消耗代理中的大量虚拟内存。如果这个参数设置得过低,那么执行复杂 SQL 的存储过程会导致 db2fmp 进程意外终止。
  • DB2_FMP_COMM_HEAPSZ: 这是一个 db2set 注册表参数。这个参数可应用于所有平台,只有 AIX 32 位平台除外,在这种平台上这个值预定义为 256MB。这个变量指定防护例程调用(比如存储过程或用户定义函数调用)所使用的池的大小(以 4 KB 页为单位)。每个防护例程所使用的空间是 ASLHEAPSZ 配置参数值的两倍。如果在系统上运行大量防护例程,那么可能需要增加这个变量的值。如果运行的防护例程很少,可以降低这个值。将这个值设置为 0 就表示不创建池,因此不能调用防护例程。可以用以下公式计算系统上可以同时运行的 db2fmp 进程的数量:
    Maximum Number of db2fmps = DB2_FMP_COMM_HEAPSZ / (2*ASLHEAPSZ)

设置 Java 环境

需要执行几个步骤,然后才能编译 Java 存储过程。本节讨论设置用于运行 Java 过程的系统所需的步骤。

兼容的 JDK/JVM 级别

在开始之前,首先确保数据库服务器上安装了兼容的 JDK/JVM。每种操作系统支持不同的 JDK 级别。如果数据库实例配置为 64 位而不是 32 位,那么这特别重要。

同一个系统上可以安装多个 JVM。为了决定在执行 Java 存储过程时使用哪个 JVM,DB2 读取 JDK_PATH 数据库管理器配置参数。需要确保 JDK_PATH 指向与环境兼容的 JVM。

设置 Java 环境

DB2 数据库服务器的平台需要正确地设置才能使用 Java。对于 Java 支持,每种平台可能有自己的需求。

对于 UNIX 平台一般的 Java 设置需求可以在以下网页上找到:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0004675.htm

对于 Windows 平台一般的 Java 设置需求可以在以下网页上找到:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0006428.htm

HPUX 和 Linux

HPUX 和 Linux 对于 Java 支持有额外的需求:

防护 id

为了执行 FENCED 存储过程,DB2 通过防护 id 方式提供了额外的安全层。这个 id(和组)应该在创建 DB2 实例时创建。可以从以下网页获得关于这个 id 的更多信息:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/t0005077.htm

配置参数

前面的 配置参数 小节提到了一组重要的配置参数。大多数这些参数可以保持默认设置。但是,当遇到问题(特别是性能问题或内存问题)时,应该检查和调整 DB2 配置参数,使之适合您的系统,这是非常重要的。

数据库特权

在大多数情况下,应用程序开发人员将开发存储过程。这一般意味着 DB2 管理员可能必须向应用程序开发人员提供必需的特权,让他们能够创建和维护这些存储过程。对于 Java 存储过程开发人员,可考虑提供以下特权:EXECUTE、CREATE_EXTERNAL_ROUTINE、CREATE_NOT_FENCED_ROUTINE、IMPLICIT_SCHEMA、CREATEIN 和 BINDADD。关于数据库特权的更多信息,请参阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/c0005524.htm

创建和部署 Java 例程

设置好环境之后,就应该能够创建和部署自己的 Java(或 SQLJ)存储过程。DB2 Application Development Client(如果安装了)包含一组示例,您在初次创建存储过程时可以参考这些示例。Java 存储过程示例位于 sqllib/samples/java/jdbc 目录中,称为 SpServer.java。SQLJ 存储过程示例位于 sqllib/samples/java/sqlj 目录,称为 SpServer.sqlj。

编写自己的例程

在编写自己的存储过程时需要考虑一些事情。需要决定为存储过程采用哪种参数传递技术。DB2 UDB 对于 Java 应用程序支持两种参数风格:

  • PARAMETER STYLE JAVA —— 这意味着存储过程将使用符合 Java 语言和 SQLJ 例程规范的参数传递约定。IN/OUT 和 OUT 参数将作为单项数组传递,以便于返回值。这只能在使用 LANGUAGE JAVA 时指定。PARAMETER STYLE JAVA 过程不支持 DBINFO 或 PROGRAM TYPE 子句。
  • PARAMETER STYLE DB2GENERAL —— 这意味着存储过程将使用为 Java 方法定义的参数传递约定。这只能在使用 LANGUAGE JAVA 时指定。PARAMETER STYLE DB2GENERAL 仍然可以用于在 Java 例程中启用以下特性的实现:表函数、scratchpad、对 DBINFO 结构进行访问以及对函数或方法进行 FINAL CALL(和单独的首次调用)。为了使用 DB2GENERAL 参数风格,需要确保存储过程的类扩展了 COM.ibm.db2.app.StoredProc。关于 PARAMETER STYLE DB2GENERAL 的更多信息,请参阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0000420.htm

在 CREATE 语句中使用 PARAMETER STYLE JAVA 子句注册 Java 例程。

与其他任何应用程序一样,存储过程需要一个 Connection context。在 Java 和 JDBC 中,这是使用来自 java.sql.* 类的 Connection 对象完成的。调用存储过程的应用程序将建立连接。所以在 Java 存储过程中,以默认连接 方式建立连接,如清单 1 所示。

清单 1. 一个名为 INSERT_JAVASP 的示例存储过程
1   //The simplest JAVA SP
2   import java.sql.*;
3 
4   public class INSERT_JAVASP
5   {
6     public static void iNSERT_JAVASP  (String input) throws SQLException,
 	Exception
7     {
8       int errorCode;
9  
10      try
11      {
12        // get caller's connection to the database
13   Connection con = DriverManager.getConnection("jdbc:default:connection");
14     
15        String query = "INSERT INTO CWYLAW.StoreData (c) VALUES (?)";
16
17        PreparedStatement pstmt = con.prepareStatement(query);
18        pstmt.setString(1, input);
19        pstmt.executeUpdate();
20  
21      }   
22      catch (SQLException sqle)
23      {
24        errorCode = sqle.getErrorCode();
25        throw new SQLException( errorCode + " FAILED" ); 
26      }
27    }
28  }

在清单 1 的第 13 行上,Connection 对象(con)被建立为 “默认” 连接。调用存储过程的应用程序将在调用过程之前建立这个连接。使用默认连接时,存储过程从调用者那里获得它的连接属性。这里显示的例子是一个 Java 存储过程,它接受一个输入参数并且将其值插入 CWYLAW.StoreData 表。

对于使用例程的限制

对于为 DB2 UDB 开发存储过程,有几个限制。一定要检查 DB2 Infocenter 的以下部分,确保自己了解这些限制:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0009198.htm

Java 类型映射

Java 支持自己的一组数据类型。DB2 也有自己的一组数据类型。例如,DB2 数据类型 VARCHAR 在 Java 中不存在。但是,Java 有一个 String 对象,可以替代这种数据类型。DB2 UDB 有一组 “首选的” 数据类型映射,适用于 Java 应用程序和存储过程。表 1(引用于 Infocenter —— 参见 参考资料)显示了这些映射。

Java 数据类型映射
SQL 类型JDBC 2.0 类型Java 类型
BIGINTBIGINTlong
BLOBBLOBjava.sql.Blob
CHARCHARString
CHAR FOR BIT DATABINARYbyte[]
CLOBCLOBjava.sql.Clob
DATEDATEjava.sql.Date
DBCLOBCLOBjava.sql.Clob
DECIMALDECIMALjava.math.BigDecimal
DOUBLEDOUBLEdouble
FLOATFLOATdouble
INTEGERINTEGERint
GRAPHICCHARString
LONG VARCHARLONGVARCHARString
LONG VARCHAR FOR BIT DATALONGVARBINARYbyte[]
LONGVARGRAPHICLONGVARCHARString
NUMERICNUMERICjava.math.BigDecimal
REALREALfloat
SMALLINTSMALLINTshort
TIMETIMEjava.sql.Time
TIMESTAMPTIMESTAMPjava.sql.Timestamp
VARCHARVARCHARString
VARCHAR FOR BIT DATAVARBINARYbyte[]
VARGRAPHICVARCHARString

编译例程

创建了存储过程之后,需要对它进行编译。使用系统上安装的 JDK,用以下命令对过程进行编译:javac INSERT_JAVASP.java

这生成一个类文件。可以将这个类文件转移到 sqllib/function 目录(这是 DB2 获得存储过程可执行文件的默认位置),也可以将它转移到您选择的另一个位置(并且在 CREATE PROCEDURE 命令中使用这个定制的路径)。

另一个办法是将类文件打包到 JAR 文件中,并且部署 JAR 文件。可以使用以下命令将类文件打包到 JAR 文件中:jar -cvf INSERT_JAVASP.jar INSERT_JAVASP.class

关于放置 Java 类的位置的更多信息,请阅读 Infocenter 的以下部分:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0006348.htm.

SQLJ 例程

在编写 SQLJ 存储过程时,需要执行两个额外的步骤:

  • 使用 DB2 SQLJ Translator 翻译 SQLJ 源代码。这会将 sqlj 代码转换成 java 代码,并且创建一个 SQLJ 可序列化(.ser)文件。
  • 定制这个可序列化文件,使嵌入语句的访问计划被存储到包中(或绑定文件中)。这需要使用 db2sqljcustomize 命令。

关于 SQLJ 的更多信息,请参阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0007588.htm

数据库服务器上的 JAR 文件管理

如果使用 JAR 文件而不是类文件,就需要采取一些额外的步骤,使 DB2 认识到 JAR 文件是存储过程类的容器。DB2 附带四个内置的存储过程,帮助管理 JAR 文件。

  • SQLJ.INSTALL_JAR :这将把 JAR 文件 “安装” 到 DB2 中,这样,当 DB2 类装载器寻找要装载的存储过程库时,它会找到并且装载这个存储过程(而不是同名的另一个存储过程)。
    语法:CALL sqlj.install_jar( jar-url, jar-id )
  • SQLJ.REPLACE_JAR:这将用一个新副本 “替换” DB2 中的 JAR 文件。如果存储过程近来由于任何变更而重新编译过,那么这个操作特别有用。这样,DB2 类装载器将在运行时重新装载具有新内容的 JAR 文件并且使用新内容。
    语法:CALL sqlj.replace_jar( jar-url, jar-id )
  • SQLJ.REMOVE_JAR:这将从 DB2 实例中 “删除” JAR 文件。如果您打算删除存储过程并且不会重新创建它,那么这个操作就有用了。这样,DB2 就不会在内存中保留这个 JAR 文件的副本。
    语法:CALL sqlj.remove_jar( jar-id )
  • SQLJ.REFRESH_CLASSES:这将在 DB2 实例中 “刷新” 一个 JAR 文件中包含的所有类。当更新 Java 例程类时,需要这样做。这使 DB2 装载新的类。如果没有使用这个命令,DB2 将使用类的旧版本。这可以与 SQLJ.REPLACE_JAR 结合使用。
    语法:CALL sqlj.refresh_classes( void )

关于 JAR 文件管理的更多信息,请参阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/r0006425.htmhttp://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0006410.htm

注册例程

在编译了存储过程(并且可选地将它存储在 JAR 文件中),并将它转移到某个位置之后,可以对存储过程进行注册,使应用程序可以引用它。

为此,需要使用 CREATE PROCEDURE 语句。在 CREATE PROCEDURE 语句中,可以为存储过程指定几个选项。下面是其中几个重要的选项:

  • SPECIFIC:这在 DB2 编目中惟一地标识存储过程名。一般来说,“SPECIFIC” 名称匹配存储过程名。
  • DYNAMIC RESULT SETS:这决定存储过程是否返回一个结果集。存储过程也可能返回多个结果集。这个选项决定过程将返回多少结果集。
  • LANGUAGE:这应该设置为 JAVA。对于 SQLJ 存储过程,也使用 JAVA。
  • EXTERNAL NAME:这个参数决定某个存储过程的类文件或 JAR 文件的位置以及文件内的方法。文件的默认位置是 sqllib/function 文件夹。也可以指定文件实际位置的完整路径。EXTERNAL NAME 子句的格式如下: ‘jar-id!class_id.method_id’‘class_id.method_id’
  • FENCED / NOT FENCED:这个参数决定存储过程是声明为 FENCED,还是 NOT FENCED。只有在您认为代码能够安全执行的情况下,才应该使用 NOT FENCED 存储过程。
  • THREADSAFE / NOT THREADSAFE:这个参数决定 FENCED 存储过程的执行是否是线程安全的。这只对定义为 FENCED 的过程起作用,因为 NOT FENCED 过程总被定义为 THREADSAFE。
  • PARAMETER STYLE:对于 Java 例程,参数风格只能是 PARAMETER STYLE JAVA 或 PARAMETER STYLE DB2GENERAL。

关于 CREATE PROCEDURE 语句的更多信息,请参阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0008328.htm

清单 2 显示一个 CREATE PROCEDURE 语句示例,其中使用了一些选项。

清单 2. CREATE PROCEDURE 语句示例
CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
;

调用例程

一旦对存储过程进行了注册,首先要做的是调用它,确保它按照预期和设计进行工作。DB2 有一个 “CALL” 命令,可以使用它调用任何存储过程。在大多数情况下,希望让应用程序使用参数标志等动态地调用存储过程。请阅读 Application Development Guide,以便确定从应用程序中调用过程的最佳方式。

然而,DB2 命令行处理程序(CLP)可以使用以下语法调用存储过程:
CALL proc-name( [parm1, parm2...] )
其中的 parm1、parm2 等等是参数。如果参数是基于字符的输入参数,那么在单引号中指定字面值。如果参数是基于数值的输入参数,那么按原样指定字面值。如果参数是输出参数,那么使用‘?’字符表示输出参数。例如:

$ db2 "CALL SHAKEBS.TESTPROC('hello', 'world', 1, 2.5, ?, 'testing')"

在这个例子中,一共有 6 个参数。第一个、第二个和第六个参数都是字符字面值。第三个参数是数值字面值,适用于 integer 或 smallint 这样的数据类型。第四个参数也是数值字面值,但是因为它包含小数点,所以应该被看作 double、float 或 decimal 类型。因为第五个参数是问号(?),所以它表示输出参数。因此,当这个存储过程被调用时,它将在这个输出参数中返回一个值。

关于 “CALL” 命令的更多信息,请参阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0011378.htmhttp://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0009000.htmhttp://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/t0007055.htm

常见问题

现在,让我们看看应用程序开发人员在开发和执行 Java(或 SQLJ)存储过程时可能遇到的一些常见问题。本文的 下载 小节中的一个 zip 文件提供了所有例子。请注意,这些例子中大部分都要求在服务器上的数据库管理器配置文件中设置 KEEPFENCED=NO

SQL4301 RC=0

清单 3 显示第一个错误的例子,sqlcode 为 SQL4301,返回码为 0。

清单 3. SQL4301 rc=0 示例 1:Windows 上的 INSERT_JAVASP.java
D:\>javac INSERT_JAVASP.java
D:\>copy INSERT_JAVASP.class "C:\Program Files\IBM\SQLLIB\Function"
        1 file(s) copied.
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
DB20000I  The SQL command completed successfully.
D:\>db2 call INSERT('D')
SQL4301N  Java or .NET interpreter startup or communication failed, reason
code "0".  SQLSTATE=58004

这个操作失败并且显示 SQL4301 rc=0 错误消息。为什么呢?检查 JDK_PATH 数据库管理器配置参数的设置是否正确。JDK_PATH 应该设置为用来执行 Java 存储过程的 JVM/JDK 的 “bin” 的上一级目录。为了纠正这个问题,检查数据库管理器配置参数 JDK_PATH,并且修改它。

清单 4. SQL4301 rc=0 示例 1:数据库管理器配置文件的片段
D:\>db2 get dbm cfg 
          Database Manager Configuration
     Node type = Enterprise Server Edition with local and remote clients
Database manager configuration release level         = 0x0a00
Maximum total of files open            (MAXTOTFILOP) = 16000
CPU speed (millisec/instruction)          (CPUSPEED) = 9.368161e-007
Communications bandwidth (MB/sec)   (COMM_BANDWIDTH) = 1.000000e+002
Max number of concurrently active databases  (NUMDB) = 8
Data Links support                       (DATALINKS) = NO
Federated Database System Support        (FEDERATED) = NO
Transaction processor monitor name     (TP_MON_NAME) =
Default charge-back account        (DFT_ACCOUNT_STR) =
Java Development Kit installation path    (JDK_PATH) = C:\PROGRA~1\IBM\
SQLLIB\java
...

注意,JDK_PATH 没有指向 “bin” 的上一级目录。这需要修改,如清单 5 所示。

清单 5. SQL4301 rc=0 示例 1:更新数据库管理器配置文件
D:\>db2 update dbm cfg using JDK_PATH C:\PROGRA~1\IBM\SQLLIB\java\jdk
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command 
completed successfully.
D:\>db2stop force
09/25/2005 14:33:16     0   0   SQL1064N  DB2STOP processing was successful.
SQL1064N  DB2STOP processing was successful.
D:\>db2start
09/25/2005 14:33:46     0   0   SQL1063N  DB2START processing was successful.
SQL1063N  DB2START processing was successful.
D:\>db2 connect to sample
   Database Connection Information
 Database server        = DB2/NT 8.2.3
 SQL authorization ID   = SHAKEBS
 Local database alias   = SAMPLE
D:\>db2 call INSERT_JAVASP('D')
  Return Status = 0
D:\>db2 "select * from CWYLAW.StoreData"
C
---
D
  1 record(s) selected.

清单 6 显示 SQL4301 rc=0 错误的另一个例子。这是由于使用了不兼容的 JVM 造成的。64 位实例需要 64 位的 JDK。32 位实例需要 32 位的 JDK。

清单 6. SQL4301 rc=0 示例 2:在 AIX 上收到 SQL4301 rc=0 错误
$ which java
/wsdb/v81/bldsupp/AIX/jdk1.4.1/bin/java
$ java -version
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1)
Classic VM (build 1.4.1, J2RE 1.4.1 IBM AIX build ca1411-20030930 (JIT enabled:
jitc))
$ db2level
DB21085I  Instance "dbguest4" uses "64" bits and DB2 code release 
"SQL08022" with level identifier "03030106".
Informational tokens are "DB2 v8.1.1.88", "s050422", "U800789", and FixPak "9".
Product is installed at "/usr/opt/db2_08_01".
$ db2 connect to sample
   Database Connection Information
 Database server        = DB2/AIX64 8.2.2
 SQL authorization ID   = DBGUEST4
 Local database alias   = SAMPLE
$ db2 "call out_language(?)"
SQL4301N  Java or .NET interpreter startup or communication failed, reason
code "0".  SQLSTATE=58004

一旦使用了适合平台的 JDK 级别,这个错误就应该消失了。

清单 7. SQL4301 rc=0 示例 2:在 AIX 上纠正 SQL4301 rc=0 错误
$ db2 connect to sample
   Database Connection Information
 Database server        = DB2/AIX64 8.2.2
 SQL authorization ID   = DBGUEST4
 Local database alias   = SAMPLE
$ db2 "call out_language(?)"
  Value of output parameters
  --------------------------
  Parameter Name  : LANGUAGE
  Parameter Value : JAVA
  Return Status = 0
$ which java
/wsdb/v81/bldsupp/AIX5L64/jdk1.4.1/bin/java
$ java -version
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1)
Classic VM (build 1.4.1, J2RE 1.4.1 IBM AIX 5L for PowerPC (64 bit JVM) 
build ca
ix641411-20030930 (JIT enabled: jitc))

常用做法是检查 db2diag.log 中的重要错误消息,由此可以判断出使用的 JDK 级别不正确。

清单 8. SQL4301 rc=0 示例 2:db2diag.log 中的相关条目
2005-10-02-18.42.36.052560-240 E226800A732        LEVEL: Error (OS)
PID     : 191200               TID  : 1           PROC : db2fmp
INSTANCE: dbguest4             NODE : 000
FUNCTION: DB2 UDB, oper system services, sqloLoadModule, probe:130
CALLED  : OS, -, dlopen
OSERR   : ENOEXEC (8) "Cannot run a file that does not have a valid format."
MESSAGE : Attempt to load specified library failed.
DATA #1 : Library name or path, 55 bytes
/wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a
DATA #2 : shared library load flags, PD_TYPE_LOAD_FLAGS, 4 bytes
2
DATA #3 : String, 145 bytes
	0509-022 Cannot load module 
   /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a.
	0509-124 The program is a discontinued 64-bit object file.

2005-10-02-18.42.36.053802-240 E227533A860        LEVEL: Error (OS)
PID     : 191200               TID  : 1           PROC : db2fmp
INSTANCE: dbguest4             NODE : 000
FUNCTION: DB2 UDB, oper system services, sqloLoadModule, probe:140
CALLED  : OS, -, dlopen
OSERR   : ENOEXEC (8) "Cannot run a file that does not have a valid format."
MESSAGE : Attempt to load specified library augmented with object name failed.
DATA #1 : Library name or path, 65 bytes
/wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a(shr_64.o)
DATA #2 : shared library load flags, PD_TYPE_LOAD_FLAGS, 4 bytes
262146
DATA #3 : String, 231 bytes
	0509-022 Cannot load module 
	   /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a(shr_64.o).
	0509-153   File /wsdb/v81/bldsupp/AIX/jdk1.4.1/jre/bin/classic/libjvm.a is 
	    not an archive or the file could not be read properly.
2005-10-02-18.42.36.058868-240 I228394A367        LEVEL: Error
PID     : 191200               TID  : 1           PROC : db2fmp
INSTANCE: dbguest4             NODE : 000
FUNCTION: DB2 UDB, oper system services, sqloJVMstart, probe:30
MESSAGE : sqloloadmodule failed.  RC:
DATA #1 : Hexdump, 4 bytes
0x0FFFFFFFFFFFC080 : 870F 009B                                  ....
2005-10-02-18.42.36.059205-240 I228762A362        LEVEL: Error
PID     : 191200               TID  : 1           PROC : db2fmp
INSTANCE: dbguest4             NODE : 000
FUNCTION: DB2 UDB, oper system services, sqloJAttach, probe:5
MESSAGE : JVM startup failed.  RC:
DATA #1 : Hexdump, 4 bytes
0x0FFFFFFFFFFFF3E0 : FFFF EF34                                  ...4
2005-10-02-18.42.36.059511-240 I229125A363        LEVEL: Error
PID     : 191200               TID  : 1           PROC : db2fmp
INSTANCE: dbguest4             NODE : 000
FUNCTION: DB2 UDB, BSU Java support, sqlejAttach, probe:10
MESSAGE : Error from sqloJAttach.  RC:
DATA #1 : Hexdump, 4 bytes
0x0FFFFFFFFFFFF4A0 : FFFF EF34                                  ...4
2005-10-02-18.42.36.060331-240 I229489A372        LEVEL: Severe
PID     : 251500               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: dbguest4             NODE : 000         DB   : SAMPLE
APPHDL  : 0-7                  APPID: *LOCAL.dbguest4.051002224226
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFmpThread, probe:20
RETCODE : ZRC=0xFFFFFBEE=-1042
2005-10-02-18.42.36.066498-240 I229862A314        LEVEL: Warning
PID     : 124744               TID  : 1           PROC : db2sysc
INSTANCE: dbguest4             NODE : 000
MESSAGE : Removing FMP from pool
DATA #1 : Hexdump, 16 bytes
0x0FFFFFFFFFFFE090 : 0000 0000 0000 0000 0002 EAE0 0002 49B8    ...I.
2005-10-02-18.44.20.194287-240 I230177A348        LEVEL: Event
PID     : 120486               TID  : 1           PROC : db2flacc
INSTANCE: dbguest4             NODE : 000
FUNCTION: DB2 UDB, config/install, sqlfLogUpdateCfgParam, probe:30
CHANGE  : CFG DBM: "JDK_path" From: "/wsdb/v81/bldsupp/AIX/jdk1.4.1" To: 
    "/wsdb/v81/bldsupp/AIX5L64/jdk1.4.1"

SQL4301 RC=2

本文中没有为 SQL4301 RC=2 错误消息提供例子,但是这种错误也值得注意。前面在讨论为 Java 存储过程支持设置环境时提到过,Linux 和 HPUX 平台需要额外的步骤。如果没有执行这些额外步骤,就会发生 SQL4301 RC=2 错误。如果您使用这些平台,那么请确保正确地设置了环境。

SQL4301 RC=4

清单 9. SQL4301 rc=4 示例:Windows 上的 INSERT_JAVASP.java
D:\>javac INSERT_JAVASP.java
D:\>copy INSERT_JAVASP.class "C:\Program Files\IBM\SQLLIB\Function"
        1 file(s) copied.     
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
DB20000I  The SQL command completed successfully.
D:\>db2 call INSERT('A')
SQL4301N  Java or .NET interpreter startup or communication failed, 
reason code "4".  SQLSTATE=58004

这个操作失败并且显示 SQL4301 rc=4 错误消息。为什么呢?检查 JAVA_HEAP_SZ 数据库管理器配置参数是否足够大,足以容纳您的 Java 存储过程。JAVA_HEAP_SZ 的默认值(512 个 4KB 页)应该足够了,但是如果出现这种错误,可以尝试将这个值加倍。

关于这个参数的更多信息,请查阅:http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0000137.htm

清单 10. SQL4301 rc=4 示例:数据库管理器配置文件片段
D:\>db2 get dbm cfg 
          Database Manager Configuration
     Node type = Enterprise Server Edition with local and remote clients
 Database manager configuration release level            = 0x0a00
 Maximum total of files open               (MAXTOTFILOP) = 16000
 CPU speed (millisec/instruction)             (CPUSPEED) = 9.368161e-007
 Communications bandwidth (MB/sec)      (COMM_BANDWIDTH) = 1.000000e+002
...
 Database monitor heap size (4KB)          (MON_HEAP_SZ) = 66
 Java Virtual Machine heap size (4KB)     (JAVA_HEAP_SZ) = 1
 Audit buffer size (4KB)                  (AUDIT_BUF_SZ) = 0
 Size of instance shared memory (4KB)  (INSTANCE_MEMORY) = AUTOMATIC
 Backup buffer default size (4KB)            (BACKBUFSZ) = 1024
 Restore buffer default size (4KB)           (RESTBUFSZ) = 1024
...

JAVA_HEAP_SZ 为 1(4K 页)显然不够运行哪怕是最简单的存储过程。在大多数情况下,默认设置 512(4K 页)应该足够了。在很少见的情况下,可能仍然会出现这个错误消息,此时可以考虑将这个配置参数再加倍。

清单 11. SQL4301 rc=4 示例:更新数据库管理器配置文件
D:\>db2 update dbm cfg using JAVA_HEAP_SZ 512
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.
  
D:\>db2stop force
09/25/2005 14:33:16     0   0   SQL1064N  DB2STOP processing was successful.
SQL1064N  DB2STOP processing was successful.
D:\>db2start
09/25/2005 14:33:46     0   0   SQL1063N  DB2START processing was successful.
SQL1063N  DB2START processing was successful.
D:\>db2 connect to sample
   Database Connection Information
 Database server        = DB2/NT 8.2.3
 SQL authorization ID   = SHAKEBS
 Local database alias   = SAMPLE
D:\>db2 call INSERT_JAVASP('A')
  Return Status = 0
D:\>db2 "select * from CWYLAW.StoreData"
C
---
A
  1 record(s) selected.

SQL4301 RC=-4301

清单 12. SQL4301 rc=-4301 示例:Windows 上的 INSERT_JAVASP.java
D:\>javac INSERT_JAVASP.java
D:\>copy INSERT_JAVASP.class "C:\Program Files\IBM\SQLLIB\Function"
        1 file(s) copied.
        
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE INSERT_JAVASP (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT_JAVASP!iNSERT_JAVASP'
DB20000I  The SQL command completed successfully.
D:\>db2 call INSERT('D')
SQL4301N  Java or .NET interpreter startup or communication failed, 
reason code "-4301".  SQLSTATE=58004

这个操作失败并且显示 SQL4301 rc=-4301 错误消息。为什么呢?检查环境变量 CLASSPATH,确保 db2java.zip 在 CLASSPATH 中。如果 db2java.zip 不在 CLASSPATH 中,就添加它。

清单 13. SQL4301 rc=-4301 示例:修改 Windows 上的环境变量 CLASSPATH
D:>set | more
ALLUSERSPROFILE=C:\Documents and Settings\All Users
APPDATA=C:\Documents and Settings\Administrator\Application Data
CLASSPATH=.;C:\Progra~1\IBM\SQLLIB\java\db2jcc.jar;C:\Progra~1\IBM\SQLLIB\
java\sqlj.zip;C:\Progra~1\IBM\SQLLIB\java\common.jar;C:\Progra~1\IBM\SQLLIB\
java\db2jcc_license_cisuz.jar;C:\Progra~1\IBM\SQLLIB\java\db2jcc_license_cu.jar
...
D:\>set CLASSPATH=%CLASSPATH%;C:\Progra~1\IBM\SQLLIB\java\db2java.zip

在这个例子中,我们在命令行上设置 CLASSPATH。这只对您登录进的用户会话有效。建议将它添加到全局环境中。在 Windows 上,可以使用 System Control Panel 来完成。在 UNIX 系统上,将 CLASSPATH 添加到用户帐户的 .profile 文件中。

清单 14. SQL4301 rc=-4301 示例:解决了 SQL4301 rc=-4301
D:\>db2 call INSERT_JAVASP('D')
  Return Status = 0
D:\>db2 "select * from CWYLAW.StoreData"
C
---
D
  1 record(s) selected.

SQL4302

SQL4302 常常意味着在 Java 存储过程代码中捕获了一个异常,或者发生了错误状况。应该检查 db2diag.log。在 DIAGLEVEL 3(默认设置)上,db2diag.log 捕获堆栈跟踪,甚至给出代码中捕获到异常处的行号。下面这个简单的例子假设编译了 Query.java 并且将 Query.class 文件复制到了 Windows 计算机的 \sqllib\FUNCTION 目录中。

清单 15. SQL4302 示例:Windows 上的 Query.java
1    import java.sql.*;
2         
3    public class Query
4    {
5       public static void query ( int id , String[] s1 ) throws 
            SQLException, Exception
6      {
7           // Get connection to the database
8           Connection con = 
            DriverManager.getConnection("jdbc:default:connection");
9           PreparedStatement stmt = null;
10          String errorLabel =  null;
11          String sql;
12                  
13          
14          sql = "SELECT NAME FROM STAFF WHERE ID = ?";
15          stmt = con.prepareStatement( sql );     
16          stmt.setInt(1, id);   
17          ResultSet rs = stmt.executeQuery();
18                  
19          if (!rs.next()) {
20             // set errorCode to SQL0100 to indicate data not found
21             errorLabel = "SQL0100 : NO DATA FOUND, QUERY RETURNS 
               EMPTY RESULT SET";
22             throw new SQLException(errorLabel);
23          } else {
24             // move to first row of result set
25             s1[0] = rs.getString(1);                
26          }   
27                  
28                  
29          // clean up resources
30          rs.close();
31          stmt.close();
32          con.close();
33                           
34          }
35   }
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE CWYLAW.QUERY (IN ID INT, OUT NAME CHAR(9))
SPECIFIC QUERY
DYNAMIC RESULT SETS 0
NOT DETERMINISTIC
LANGUAGE JAVA
EXTERNAL NAME 'Query.query'
FENCED
THREADSAFE
PARAMETER STYLE JAVA
DB20000I  The SQL command completed successfully.
D:\>db2 call query(5, ?)
SQL4302N  Procedure or user-defined function "CWYLAW.QUERY", 
specific name "QUERY" aborted with an exception "SQL0100 : 
NO DATA FOUND, QUERY RETURNS EMPTY RESULT".  SQLSTATE=38501
D:\>db2 call query(10, ?)
  Value of output parameters
  --------------------------
  Parameter Name  : NAME
  Parameter Value : Sanders
  Return Status = 0

SQL4302 错误并不代表严重的错误。实际上,这是一个好信号。它意味着 Java 代码中的异常处理程序工作正常,并且捕获到了一个异常。在下面您将看到,db2diag.log 实际上告诉您在 Query.java 的第 22 行捕获了这个异常。在这个例子中 SQL4302 告诉我们,过程中的查询 SELECT NAME FROM STAFF WHERE ID = 5 返回一个空的结果集。如果提供一个有效的 ID(比如 10),那么这个存储过程将返回一个名称(在本例中是 Sanders)。

清单 16. SQL4302 示例:db2diag.log 中的相关条目
2005-10-02-21.51.36.325000-240 I79282H396         LEVEL: Warning
PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
INSTANCE: DB2                  NODE : 000
FUNCTION: DB2 UDB, BSU Java support, sqlejCallJavaRoutine_dll, probe:315
MESSAGE : Exception thrown during routine invocation:
DATA #1 : Hexdump, 4 bytes
0x01ACF5EC : D480 5501                                  ..U.
2005-10-02-21.51.36.335000-240 E79680H375         LEVEL: Warning
PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
INSTANCE: DB2                  NODE : 000
FUNCTION: DB2 UDB, BSU Java support, sqlejLogException, probe:10
MESSAGE : ADM10000W  A Java exception has been caught.  The Java stack 
          traceback has been written to the db2diag.log.
2005-10-02-21.51.36.345000-240 I80057H475         LEVEL: Warning
PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
INSTANCE: DB2                  NODE : 000
FUNCTION: DB2 UDB, BSU Java support, sqlejLogException, probe:10
DATA #1 : String, 112 bytes
java.sql.SQLException: SQL0100 : NO DATA FOUND, QUERY RETURNS EMPTY 
  RESULT SET at Query.query(Query.java:22)
DATA #2 : Hexdump, 4 bytes
0x01ACF424 : 0000 0000                                  ....
2005-10-02-21.51.36.355000-240 I80534H384         LEVEL: Warning
PID     : 2140                 TID  : 2684        PROC : db2fmp.exe
INSTANCE: DB2                  NODE : 000
FUNCTION: DB2 UDB, routine_infrastructure, sqlerJavaCallRoutine, probe:30
MESSAGE : Error from DB2ER CallUDF.  RC:
DATA #1 : Hexdump, 4 bytes
0x01ACF97C : 32EF FFFF                                  2...
2005-10-02-21.51.36.365000-240 I80920H959         LEVEL: Error
PID     : 3632                 TID  : 2840        PROC : db2bp.exe
INSTANCE: DB2                  NODE : 000
APPID   : *LOCAL.DB2.051003014530
FUNCTION: DB2 UDB, oper system services, sqlofica, probe:10
DATA #1 : Hexdump, 136 bytes
0x0012FC90 : 5351 4C43 4120 2020 8800 0000 32EF FFFF    SQLCA   ....2...
0x0012FCA0 : 4600 4357 594C 4157 2E51 5545 5259 FF51    F.CWYLAW.QUERY.Q
0x0012FCB0 : 5545 5259 FF53 514C 3031 3030 203A 204E    UERY.SQL0100 : N
0x0012FCC0 : 4F20 4441 5441 2046 4F55 4E44 2C20 5155    O DATA FOUND, QU
0x0012FCD0 : 4552 5920 5245 5455 524E 5320 454D 5054    ERY RETURNS EMPT
0x0012FCE0 : 5920 5245 5355 4C54 5351 4C45 4A45 5854    Y RESULTSQLEJEXT
0x0012FCF0 : 0000 0000 0000 0000 0000 0000 0000 0000    ................
0x0012FD00 : 0000 0000 0000 0000 2020 2020 2020 2020    ........        
0x0012FD10 : 2020 2033 3835 3031                           38501

SQL4304 RC=1

清单 17. SQL4304 rc=1 示例:AIX 上的 SQL4304RC1.java
$ javac SQL4304RC1.java
$ cp SQL4304RC1.class ~/sqllib/function
$ db2 -tvf CreateSP_wrong.ddl
CREATE PROCEDURE SQL4304RC1 (IN INPUT int)
SPECIFIC SQL4304RC1
DYNAMIC RESULT SETS 1
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE DB2GENERAL
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'SQ4304RC1!abend'
DB20000I  The SQL command completed successfully.
$ db2 "call SQL4304RC1(3)"
SQL4304N  Java stored procedure or user-defined function "SHAKEBS.SQL4304RC1",
specific name "SQL4304RC1" could not load Java class "SQ4304RC1", reason code
"1".  SQLSTATE=42724

这个操作失败并且显示 SQL4304 rc=1 错误消息。为什么呢?注意,EXTERNAL NAME 子句中的类名拼写错了(它应该是 SQL4304RC1!abend,缺少了 “L”)。要纠正这个错误,应该删除这个过程,并且在 EXTERNAL NAME 子句中采用正确的拼写来重新创建它。

清单 18. SQL4304 rc=1 示例:纠正 SQL4304 rc=1 错误
$ db2 drop procedure SQL4304RC1
DB20000I  The SQL command completed successfully.
$ db2 -tvf CreateSP.ddl
CREATE PROCEDURE SQL4304RC1 (IN INPUT int)
SPECIFIC SQL4304RC1
DYNAMIC RESULT SETS 1
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE DB2GENERAL
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'SQL4304RC1!abend'
DB20000I  The SQL command completed successfully.
$ db2 "call SQL4304RC1(3)"
  Result set 1
  --------------
  ID     NAME      DEPT   JOB   YEARS  SALARY    COMM
  ------ --------- ------ ----- ------ --------- ---------
     180 Abrahams      38 Clerk      3  12009.75    236.50
     230 Lundquist     51 Clerk      3  13369.80    189.65
  2 record(s) selected.
  Return Status = 0

SQL4304 RC=2

清单 19. SQL4304 rc=2 示例:AIX 上的 SQL4304RC2.java
$ javac SQL4304RC2.java
$ cp SQL4304RC2.class ~/sqllib/function
$ db2 -tvf CreateSP_wrong.ddl
CREATE PROCEDURE SQL4304RC2 (IN INPUT int)
SPECIFIC SQL4304RC2
DYNAMIC RESULT SETS 1
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE DB2GENERAL
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'SQL4304RC2!abend'
DB20000I  The SQL command completed successfully.
$ db2 "call SQL4304RC2(3)"
SQL4304N  Java stored procedure or user-defined function "SHAKEBS.SQL4304RC2",
specific name "SQL4304RC2" could not load Java class "SQL4304RC2", reason code
"2".  SQLSTATE=42724

这个操作失败并且显示 SQL4304 rc=2 错误消息。为什么呢?因为 PARAMETER STYLE 是 DB2GENERAL,所以需要确保 Java 源代码扩展 COM.ibm.db2.app.StoredProc。为了纠正这个问题,将 extends COM.ibm.db2.app.StoredProc 添加到存储过程类名的末尾。

清单 20. SQL4304 rc=2 示例:SQL4304RC2.java
1    //The simplest JAVA SP
2    import java.sql.*;
3    import COM.ibm.db2.app.*;
4     
5    public class SQL4304RC2 extends COM.ibm.db2.app.StoredProc
6    { 
7      public void abend  (int input) throws SQLException,Exception
8      {  
9        int errorCode;
10   
11       try
12       {
13         // get caller's connection to the database
14         Connection con = DriverManager.getConnection("jdbc:default:connection");
15     
16         String query = "SELECT * FROM STAFF where YEARS = ?";
17
18         PreparedStatement pstmt = con.prepareStatement(query);
19         ResultSet rs = null;
20         pstmt.setInt(1, input);
21         rs = pstmt.executeQuery();
22    
23       } 
24       catch (SQLException sqle)
25       {
26         errorCode = sqle.getErrorCode();
27         throw new SQLException( errorCode + " FAILED - " + sqle.getMessage()); 
28       }  
29     }
30   }

代码中的第 5 行现在正确地扩展类。重新对代码进行编译,然后替换 sqllib/function 中的 .class 文件,并且重新执行存储过程。

注意:导致 SQL4304 rc=2 错误消息的另一个常见错误是,存储过程的主方法被声明为 “public static” 方法。PARAMETER STYLE DB2GENERAL 过程不能声明为 “static” 方法,像以上代码的第 7 行那样进行声明才是正确的。

清单 21. SQL4304 rc=2 示例:纠正 SQL4304 rc=2 错误
$ javac SQL4304RC2.java
$ cp SQL4304RC2.class ~/sqllib/function
$ db2 "call SQL4304RC2(3)"
  Result set 1
  --------------
  ID     NAME      DEPT   JOB   YEARS  SALARY    COMM
  ------ --------- ------ ----- ------ --------- ---------
     180 Abrahams      38 Clerk      3  12009.75    236.50
     230 Lundquist     51 Clerk      3  13369.80    189.65
  2 record(s) selected.
  Return Status = 0

SQL4306

清单 22. SQL4306 示例:INSERT.sqlj
D:\>sqlj INSERT.sqlj
   
D:\>db2sqljcustomize -user cwylaw -password xxxxxxxxx -url 
   jdbc:db2://claw.torolab.ibm.com:50000/sample INSERT_SJProfile0
[ibm][db2][jcc][sqlj]
[ibm][db2][jcc][sqlj] Begin Customization
[ibm][db2][jcc][sqlj] Loading profile: INSERT_SJProfile0
[ibm][db2][jcc][sqlj] Customization complete for profile 
    INSERT_SJProfile0.ser
[ibm][db2][jcc][sqlj] Begin Bind
[ibm][db2][jcc][sqlj] Loading profile: INSERT_SJProfile0
[ibm][db2][jcc][sqlj] Driver defaults(user may override): BLOCKING ALL 
    VALIDATE BIND STATICREADONLY YES
[ibm][db2][jcc][sqlj] Fixed driver options: DATETIME ISO DYNAMICRULES BIND
[ibm][db2][jcc][sqlj] Binding package INSERT01 at isolation level UR
[ibm][db2][jcc][sqlj] Binding package INSERT02 at isolation level CS
[ibm][db2][jcc][sqlj] Binding package INSERT03 at isolation level RS
[ibm][db2][jcc][sqlj] Binding package INSERT04 at isolation level RR
[ibm][db2][jcc][sqlj] Bind complete for INSERT_SJProfile0
D:\>jar -cvf INSERT.jar *.class *.ser
added manifest
adding: INSERT.class(in = 1192) (out= 684)(deflated 42%)
D:\>db2 call sqlj.install_jar("file:///D:\INSERT.jar", 
'INSERTJAR')
DB20000I  The CALL command completed successfully.
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE INSERT (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT.INSERT'
DB20000I  The SQL command completed successfully.
D:\>db2 call INSERT('abc')
SQL4306N  Java stored procedure or user-defined function "CWYLAW.INSERT",
specific name "INSERT" could not call Java method "INSERT", 
signature "(Ljava/lang/String;)V".  SQLSTATE=42724

为什么会产生这个 SQL4306 错误?请看看源代码和 CREATE PROCEDURE 语句。注意,在 Java 代码中,方法被声明为:public static void iNSERT (String input)

注意小写字母‘i’。

清单 23. SQL4306 示例:Windows 上的 INSERT.sqlj
//The simplest SQLJ SP
import java.sql.*;
import sqlj.runtime.*; 
import sqlj.runtime.ref.*; 
 
public class INSERT 
{
  public static void iNSERT (String input) throws SQLException, Exception
 
    { 
    	#sql { INSERT INTO CWYLAW.StoreData (c) VALUES (:input) }; 
    }  
}
清单 24. SQL4306 示例:INSERT 过程所需的 StoreData 表的 CREATE TABLE 语句
CREATE TABLE StoreData (c char(3));

但是,在 CREATE PROCEDURE 语句中,EXTERNAL NAME 被声明为 EXTERNAL NAME 'INSERT.INSERT'。注意大写字母‘I’。所以,出现 SQL4306 错误的原因是源代码中的 Java 方法名与 CREATE PROCEDURE 语句中的 EXTERNAL NAME 不匹配。要纠正这个问题,就要确保 Java 方法与 CREATE PROCEDURE 语句中的 EXTERNAL NAME 子句精确匹配。在这个例子中,我们选择修改 CREATE PROCEDURE 语句而不是修改源代码。

清单 25. SQL4306 示例:INSERT 存储过程的正确的 CREATE PROCEDURE 语句
CREATE PROCEDURE INSERT (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT.iNSERT'
;

现在,INSERT 过程能够成功运行了。

清单 26. 运行 INSERT 过程
D:\>db2 drop procedure INSERT
DB20000I  The SQL command completed successfully.
D:\>db2 call sqlj.remove_jar('INSERTJAR')
DB20000I  The CALL command completed successfully.
D:\>db2 call sqlj.install_jar("file:///D:\INSERT.jar", 'INSERTJAR')
DB20000I  The CALL command completed successfully.
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE INSERT (IN INPUT CHAR(3))
SPECIFIC INSERT
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'INSERT.iNSERT'
DB20000I  The SQL command completed successfully.
D:\>db2 call INSERT('abc')
  Return Status = 0
  
D:\>db2 select * from StoreData
C
---
abc
  1 record(s) selected.

还应该花点儿时间看看类型签名的 JVM 表示,因为这可以帮助您在遇到 SQL4306 错误时识别出问题。SQL4306 错误的另一个常见原因是过程的参数与 Java 方法定义不匹配。在这个例子中,SQL4306 错误的末尾包含一个含义有点儿模糊的错误符号:

清单 27. SQL4306 错误显示了 JVM 返回的 Java 类型
SQL4306N  Java stored procedure or user-defined function "CWYLAW.INSERT",
specific name "INSERT" could not call Java method "INSERT", signature
"(Ljava/lang/String;)V".  SQLSTATE=42724

(Ljava/lang/String;)V 实际上是 JVM 返回的 Java 类型签名。

表 2. Java VM 类型签名
类型签名Java 类型
Zboolean
Bbyte
Cchar
Sshort
Iint
Jlong
Ffloat
Ddouble
L fully-qualified-class ;fully-qualified-class
[ typetype[]
( arg-types ) ret-typemethod type

所以这个错误消息指出,DB2 试图调用 Java 存储过程 INSERT,这个过程的 Java VM 类型签名是 (Ljava/lang/String;)V,其中 fully-qualified-classjava/lang/String(即,输入参数是类型 String),返回类型是 V,代表类型 void。这精确地匹配 Java 方法定义:

public static void iNSERT (String input)

现在,已经证实 Java VM 签名是正确的,所以确定了问题不是 由于过程参数与 Java 方法定义不匹配而引起的。正如在前面发现的,EXTERNAL NAME 与 Java 方法定义不匹配是问题的原因。而且与前面一样,可以通过重新发出正确的 CREATE PROCEDURE 语句来纠正这个问题。关于 Java VM 类型签名的更多信息,请访问以下 URL:

http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/types.html

SQL20200

SQL20200 错误表示无法找到 JAR 文件。这往往意味着 JAR URL 是错的,或者 DB2 无法找到 JAR 文件。在这个简单的例子中,JAR 文件不存在,这造成了 SQL20200 错误:

清单 28. SQL20200 示例:AIX 上的 OUT_20200.java
cwylaw@bugdbug:/home/cwylaw> javac Out_20200.java
cwylaw@bugdbug:/home/cwylaw> db2 connect to sample
   Database Connection Information
 Database server        = DB2/6000 8.2.3
 SQL authorization ID   = CWYLAW
 Local database alias   = SAMPLE
cwylaw@bugdbug:/home/cwylaw> db2 "call 
sqlj.install_jar('file:/home/cwylaw/Out_20200.jar','OUT20200JAR')"
SQL20200N  The install or replace of "CWYLAW  .OUT20200JAR" failed as
"/home/cwylaw/Out_20200.jar" could not be located.
SQLSTATE=46001

这个错误消息明确地指出无法找到 JAR 文件。在这种情况中,办法很简单。需要确保 JAR 文件名 Out_20200.jar 是正确的,并且这个文件在 /home/cwylaw/ 目录中,然后再次安装 JAR 文件。在这个例子中,在调用 sqlj.install_jar 例程安装 JAR 文件之前没有创建 JAR 文件。创建 JAR 文件并且再次安装它。

清单 29. SQL20200 示例:通过创建 JAR 文件纠正问题
cwylaw@bugdbug:/home/cwylaw> ls
Create.ddl       Out_20200.class  Out_20200.java
cwylaw@bugdbug:/home/cwylaw> jar -cvf Out_20200.jar *.class
adding: Out_20200.class (in=1466) (out=862) (deflated 41%)
cwylaw@bugdbug:/home/cwylaw> ls
Create.ddl       Out_20200.jar    Out_20200.class
Out_20200.java
cwylaw@bugdbug:/home/cwylaw> db2 "call 
sqlj.install_jar('file:/home/cwylaw/Out_20200.jar','OUT20200JAR')"
DB20000I  The CALL command completed successfully.

SQL20201

SQL20201 的示例使用前面的 SQL4306 示例中使用过的 INSERT 存储过程来演示 SQL20201 问题。在以下情况中会出现 SQL20201 错误:

  • 试图删除并且重新创建存储过程,但是在再次调用 sqlj.install_jar 之前没有删除 JAR 文件。
  • 试图删除具有无效 JAR ID 的 JAR 文件。
清单 30. SQL20201 示例 1:在 Windows 上安装 JAR 文件时出现的错误
D:\>db2 drop procedure INSERT
DB20000I  The SQL command completed successfully.
D:\>db2 call sqlj.install_jar("file:///D:\INSERT.jar", 'INSERTJAR')
SQL20201N  The install, replace or remove of "CWYLAW  .INSERTJAR" failed as
the jar name is invalid.  SQLSTATE=46002

对于第一种情况,必须先调用 sqlj.remove_jar,然后再调用 sqlj.install_jar 来再次安装 JAR 文件。还可以简单地调用 sqlj.replace_jar,用更新的类文件替换 JAR 文件。

清单 31. SQL20201 示例 1:通过首先删除 JAR 文件或者简单地替换 JAR 文件来纠正问题
D:\>db2 call sqlj.remove_jar('INSERTJAR')
DB20000I  The CALL command completed successfully.
D:\>db2 call sqlj.install_jar("file:///D:\INSERT.jar", 'INSERTJAR')
DB20000I  The CALL command completed successfully.

或者简单地调用 sqlj.replace_jar 来替换 JAR 文件:

D:\>db2 call sqlj.replace_jar("file:///D:\INSERT.jar", 'INSERTJAR')
DB20000I  The CALL command completed successfully.
清单 32. SQL20201 示例 2:在 Windows 上删除 JAR 文件时发生的错误
D:\>db2 call sqlj.remove_jar('OUT20200')
SQL20201N  The install, replace or remove of "CWYLAW  .OUT20200" failed 
   as the jar name is invalid.  SQLSTATE=46002

以上错误消息指出 JAR ID CWYLAW.OUT20200 是无效的。确保提供正确的 JAR ID,并且再次尝试删除 JAR 文件。在这个例子中,正确的 JAR ID 是 OUT20200JAR不是OUT20200(参见前面的 SQL20200 例子)。所以,现在如果再次尝试删除 JAR,就会成功:

清单 33. SQL20201 示例 2:通过提供正确的 JAR ID 来纠正问题
D:\>db2 call sqlj.remove_jar('OUT20200JAR')
DB20000I  The CALL command completed successfully.

SQL20204

对于 SQL20204,最常见的问题是 CREATE PROCEDURE 中的 EXTERNAL NAME 不符合正确的格式。正确的格式如下:

清单 34. Java EXTERNAL NAME 格式
>>-'--+----------+--class_id--+-.-+--method_id--'--------------><
      '-jar_id :-'            '-!-'
清单 35. SQL20204 示例:Windows 上 SQL20204 错误的示例
D:\>db2 call sqlj.install_jar("file:///D:\Out_Language.jar",'OUTLANGUAGEJAR')
DB20000I  The CALL command completed successfully.
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE OUT_LANGUAGE (OUT LANGUAGE CHAR(8))
SPECIFIC OUT_LANGUAGE
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
READS SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'OUT_LANGUAGE:Out_Language!outLanguage'
DB21034E  The command was processed as an SQL statement because it was not a
valid Command Line Processor command.  During SQL processing it returned:
SQL20204N  The user defined function or procedure "CWYLAW.OUT_LANGUAGE" was
unable to map to a single Java method.  LINE NUMBER=10.  SQLSTATE=46008

在上面,EXTERNAL NAME 让 DB2 寻找具有名称 OUT_LANGUAGE 的 JAR ID,其中类名是 Out_Language,Java 方法是 outLanguage。但是 DB2 无法找到这个 Java 方法。为了处理这个问题,应该检查:

  1. 是否为这个 OUT_LANGUAGE 存储过程创建了 JAR 文件?如果创建了,那 JAR ID 名称正确吗?
  2. 类文件名正确吗?类文件存在吗?
  3. Java 方法名正确吗?

那么,是什么造成了这个 SQL20204 问题?看看 Out_Language.java 文件中的源代码片段:

清单 36. SQL20204 示例:Out_Language.java 中的类和 Java 方法定义
public class Out_Language {
     public static void outLanguage(String[] outLanguage)
...

从上面的代码可以看出,类文件名是正确的(Out_Language)。Java 方法名也是正确的(outLanguage)。所以,最后要检查的是 JAR ID 是否正确。注意,在前面的 sqlj.install_jar 步骤中,JAR 是用 JAR ID OUTLANGUAGEJAR 安装的。但是,在 CREATE PROCEDURE 语句的 EXTERNAL NAME 子句中指定的是 OUT_LANGUAGE:Out_Language!outLanguage。也就是说,JAR ID 成了 OUT_LANGUAGE 而不是 OUTLANGUAGEJAR。要纠正这个问题,应该在 EXTERNAL NAME 子句中使用正确的 JAR ID:

清单 37. SQL20204 示例:OUT_LANGUAGE 过程的正确的 CREATE PROCEDURE 语句
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE OUT_LANGUAGE (OUT LANGUAGE CHAR(8))
SPECIFIC OUT_LANGUAGE
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
READS SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'OUTLANGUAGEJAR:Out_Language!outLanguage'
DB20000I  The SQL command completed successfully.

SQL0449

SQL0449 错误与 SQL20204 的情况非常相似。如果出现了 SQL0449 错误,大多数时候是因为 EXTERNAL NAME 子句的格式无效。

清单 38. SQL449 示例:无效的 EXTERNAL NAME
D:\>db2 connect to sample
   Database Connection Information
 Database server        = DB2/NT 8.2.2
 SQL authorization ID   = CWYLAW
 Local database alias   = SAMPLE
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE OUT_LANGUAGE (OUT LANGUAGE CHAR(8))
SPECIFIC OUT_LANGUAGE
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
READS SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'Out_Language:outLanguage'
DB21034E  The command was processed as an SQL statement because it was not a
valid Command Line Processor command.  During SQL processing it returned:
SQL0449N  The statement defining routine "CWYLAW.OUT_LANGUAGE" contains an
invalidly formatted library/function identification in the EXTERNAL NAME
clause.  LINE NUMBER=10.  SQLSTATE=42878

这个错误消息指出 EXTERNAL NAME 子句是一个格式无效的字符串。正如前面 SQL20202 示例中讨论的,正确的 Java EXTERNAL NAME 格式如下:

清单 39. Java EXTERNAL NAME 格式
>>-'--+----------+--class_id--+-.-+--method_id--'--------------><
      '-jar_id :-'            '-!-'

出现这个错误是因为‘:’只用于分隔 JAR ID 与类 ID。它不能用于分隔类 ID 与方法 ID。在这个例子中,我们希望让 DB2 寻找类 Out_Language 中的 Java 方法 outLanguage。因此,要纠正这个问题,应该使用‘!’或‘.’替代‘:’。

清单 40. SQL449 示例:具有有效 EXTERNAL NAME 的正确 CREATE PROCEDURE 语句
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE OUT_LANGUAGE (OUT LANGUAGE CHAR(8))
SPECIFIC OUT_LANGUAGE
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
READS SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'Out_Language!outLanguage'
DB20000I  The SQL command completed successfully.
D:\>db2 call out_language(?)
  Value of output parameters
  --------------------------
  Parameter Name  : LANGUAGE
  Parameter Value : JAVA
  return Status = 0

现在,CREATE PROCEDURE 语句成功了,存储过程成功运行。

SQL0444

对于 SQL0444,涉及 Java 存储过程的常见问题包括:

  • SQL0444 RC=4 —— 这常常表示无法找到库或路径。在大多数情况下,在 fixpak 升级之后安装或替换 JAR 文件时,或试图构建 Java 存储过程时可能产生这个错误。

    解决方案: 针对数据库运行 db2updv8 或者针对实例运行 db2iupdt(或者同时采用这两个操作)。发生 SQL0444 RC=4 错误是因为在 fixpak 升级之后数据库需要更新到当前的 fixpak 级别,而且实例链接需要刷新。

  • SQL0444 RC=9 —— 在执行 Java 存储过程时可能发生这个错误。大多数时候,这是由于内存不足。

    解决方案: 检查 ulimit 设置,还要检查实例的 DBM CFG 参数以及数据库的 DB CFG 参数。可能需要调整这些参数,让更多的内存供运行 Java 存储过程使用。要检查的一些重要参数是:

    • java_heap_sz —— 最大 Java 解释器堆大小配置参数
    • query_heap_sz —— 查询堆大小配置参数
    • aslheapsz —— 应用程序支持层堆大小配置参数

    在大多数情况下,可能需要增加 java_heap_szquery_heap_sz,但是降低 aslheapsz

SQL0440

SQL0444 错误表示无法找到具有匹配的参数的过程。这个错误不表示严重的问题,在运行时这常常发生。有两个原因:

  • 没有通过发出 CREATE PROCEDURE 语句在当前服务器上定义过程。因此 DB2 无法定位这个过程。

    解决方案: 发出 CREATE PROCEDURE 语句。

  • 调用过程时参数的数量不正确。即,提供的输入或输出参数的数量不正确,或者某个参数的数据类型不正确。因此,DB2 无法找到具有匹配的参数的过程。

    解决方案: 检查 CREATE PROCEDURE 语句,确保传递的输入和输出参数的数量和数据类型都正确。

下面是第二种情况的例子,即在运行时传递给过程的参数数量不正确。这个例子使用 DB2 产品附带的示例存储过程 OUT_LANGUAGEALL_DATA_TYPES。在 UNIX 平台上,源代码在 /instance_home/sqllib/samples/java/jdbc/SpServer.java 中,对应的 CREATE PROCEDURE 语句在 /instance_home/sqllib/samples/java/jdbc/SpCreate.db2 中,其中的 instance_home 是数据库实例的主目录。在 Windows 上,这些文件的默认位置是 C:\Program Files\IBM\SQLLIB\samples\java\jdbc\SpServer.java 和 C:\Program Files\IBM\SQLLIB\samples\java\jdbc\SpCreate.db2。

清单 41. SQL0440 示例:在 Windows 上调用 OUT_LANGUAGE() 和 ALL_DATA_TYPES 过程
D:\>db2 call out_language()
SQL0440N  No authorized routine named "OUT_LANGUAGE" of type "PROCEDURE"
having compatible arguments was found.  SQLSTATE=42884
D:\>db2 call all_data_types (32000, 2147483000, 21478483000, 100000, 2500000)
SQL0440N  No authorized routine named "ALL_DATA_TYPES" of type "PROCEDURE"
having compatible arguments was found.  SQLSTATE=42884

我们来看看为什么会返回 SQL0440。先看一下 CREATE PROCEDURE 语句,确定每个存储过程所需要的参数。

清单 42. SQL0440 示例:OUT_LANGUAGE 和 ALL_DATA_TYPES 过程的 CREATE PROCEDURE 语句
CREATE PROCEDURE OUT_LANGUAGE (OUT LANGUAGE CHAR(8))
SPECIFIC JDBC_OUT_LANGUAGE
DYNAMIC RESULT SETS 0
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
READS SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'SpServer.outLanguage'
CREATE PROCEDURE ALL_DATA_TYPES (
  INOUT small SMALLINT, 
  INOUT intIn INTEGER,
  INOUT bigIn BIGINT,
  INOUT realIn REAL, 
  INOUT doubleIn DOUBLE,
  OUT charOut CHAR(1),
  OUT charsOut CHAR(15),
  OUT varcharOut VARCHAR(12),
  OUT dateOut DATE,
  OUT timeOut TIME)
SPECIFIC JDBC_ALL_DAT_TYPES
DYNAMIC RESULT SETS 0
NOT DETERMINISTIC
LANGUAGE JAVA 
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
READS SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'SpServer.allDataTypes'

从 CREATE PROCEDURE 语句可以看出:

  1. OUT_LANGUAGE 过程需要一个 char 类型的输出参数。
  2. ALL_DATA_TYPES 过程需要 5 个输入/输出参数和 5 个输出参数,参数类型如上所示。

对于输入参数,提供具有正确数据类型的正确值。对于每个输出参数,使用一个‘?’。对于输入/输出参数,因为它们用于输入和输出两种用途,所以要像对待输入参数那样提供正确的值。因此,应该像下面这样调用这些过程:

清单 43. SQL0440 示例:正确地调用 OUT_LANGUAGE 和 ALL_DATA_TYPES 过程
D:\>db2 call out_language(?)
  Value of output parameters
  --------------------------
  Parameter Name  : LANGUAGE
  Parameter Value : JAVA
  Return Status = 0
D:\>db2 call all_data_types (32000, 2147483000, 21478483000, 100000, 
2500000, ?, ?, ?, ?, ?)
  Value of output parameters
  --------------------------
  Parameter Name  : SMALL
  Parameter Value : 16000
  Parameter Name  : INTIN
  Parameter Value : 1073741500
  Parameter Name  : BIGIN
  Parameter Value : 10739241500
  Parameter Name  : REALIN
  Parameter Value : +5.00000E+004
  Parameter Name  : DOUBLEIN
  Parameter Value : +1.25000000000000E+006
  Parameter Name  : CHAROUT
  Parameter Value : S
  Parameter Name  : CHARSOUT
  Parameter Value : SCOUTTEN
  Parameter Name  : VARCHAROUT
  Parameter Value : MARILYN
  Parameter Name  : DATEOUT
  Parameter Value : 09/27/2005
  Parameter Name  : TIMEOUT
  Parameter Value : 11:30:16
  Return Status = 0

关于如何从命令行处理程序(CLP)调用过程的更多信息,请访问:http://publib.boulder.ibm.com/infocenter/db2help/index.jsp?topic=/com.ibm.db2.udb.doc/ad/t0007055.htm

SQL1042

尽管错误消息 “SQL1042C An unexpected system error occurred” 听起来非常严重,但是不必担心。常常能够纠正这个问题。当看到这个 SQL1042 错误时,一定要检查 db2diag.log,因为这个日志文件常常包含有用的信息,可以指出造成问题的原因。最常见的问题是:

  1. 安装 JAR 文件时的 SQL1042

    解决方案 1: 检查是否执行了适合平台的所有 Java 设置步骤。在 UNIX 平台上出现这个问题很可能是因为对于 HPUX 和 Linux 需要特殊的 Java 设置步骤。还要检查并且确保创建了正确的符号链接,指向适合平台的 Java 共享库。请参考前面的 “设置 Java 环境” 小节。

    解决方案 2: 检查是否存在权限问题,造成 DB2 不能访问 /sqllib/function/jar 目录。出现 SQL1042 还可能是因为无效的路径名或不可访问的网络路径。

  2. 调用存储过程时的 SQL1042

    解决方案 1: 检查 ASLHEAPSZ 和/或 QUERY_HEAP_SZ 参数。

    解决方案 2: 检查 DB2_FMP_COMM_HEAPSZ 注册表变量。

清单 44. SQL1042 示例 1:在安装 JAR 文件期间造成 SQL1042 的权限问题
cwylaw@bugdbug:/home/cwylaw> javac Out_20200.java
cwylaw@bugdbug:/home/cwylaw> jar -cvf Out_20200.jar *.class
cwylaw@bugdbug:/home/cwylaw> db2 connect to sample
   Database Connection Information
 Database server        = DB2/6000 8.2.3
 SQL authorization ID   = CWYLAW
 Local database alias   = SAMPLE
 
 
cwylaw@bugdbug:/home/cwylaw> db2 "call 
sqlj.install_jar('file:/home/cwylaw/Out_20200.jar','OUT20200')"
SQL1042C  An unexpected system error occurred.  SQLSTATE=58004

需要检查 db2diag.log 来获得更多信息。

清单 45. SQL1042 示例 1:在安装 JAR 文件期间造成 SQL1042 的权限问题。相关的 db2diag.log 条目
2005-09-29-11.32.42.602876-240 E102575C539        LEVEL: Warning (OS)
PID     : 214958               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-265                APPID: *LOCAL.cwylaw.050929151244
FUNCTION: DB2 UDB, oper system services, sqlomkdirp, probe:100
CALLED  : OS, -, unspecified_system_function
OSERR   : EACCES (13) "The file access permissions do not allow 
the specified action."
DATA #1 : File name, 39 bytes
/home/cwylaw/sqllib/function/jar/CWYLAW

2005-09-29-11.32.42.627442-240 I103115C588        LEVEL: Error
PID     : 214958               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-265                APPID: *LOCAL.cwylaw.050929151244
FUNCTION: DB2 UDB, oper system services, sqlomkdirp, probe:10
MESSAGE : directory:
DATA #1 : Hexdump, 39 bytes
0x2FF11FB0 : 2F68 6F6D 652F 6377 796C 6177 2F73 716C    /home/cwylaw/sql
0x2FF11FC0 : 6C69 622F 6675 6E63 7469 6F6E 2F6A 6172    lib/function/jar
0x2FF11FD0 : 2F43 5759 4C41 57                          /CWYLAW
2005-09-29-11.32.42.627837-240 I103704C440        LEVEL: Error
PID     : 214958               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-265                APPID: *LOCAL.cwylaw.050929151244
FUNCTION: DB2 UDB, oper system services, sqlomkdirp, probe:20
MESSAGE : permissions:
DATA #1 : Hexdump, 4 bytes
0x2FF11E4C : 0000 01FD                                  ...
2005-09-29-11.33.35.148685-240 E104145C539        LEVEL: Warning (OS)
PID     : 214958               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-291                APPID: *LOCAL.cwylaw.050929153332
FUNCTION: DB2 UDB, oper system services, sqlomkdirp, probe:100
CALLED  : OS, -, unspecified_system_function
OSERR   : EACCES (13) "The file access permissions do not allow the 
specified action."
DATA #1 : File name, 39 bytes
/home/cwylaw/sqllib/function/jar/CWYLAW
2005-09-29-11.33.35.149550-240 I104685C588        LEVEL: Error
PID     : 214958               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-291                APPID: *LOCAL.cwylaw.050929153332
FUNCTION: DB2 UDB, oper system services, sqlomkdirp, probe:10
MESSAGE : directory:
DATA #1 : Hexdump, 39 bytes
0x2FF11FB0 : 2F68 6F6D 652F 6377 796C 6177 2F73 716C    /home/cwylaw/sql
0x2FF11FC0 : 6C69 622F 6675 6E63 7469 6F6E 2F6A 6172    lib/function/jar
0x2FF11FD0 : 2F43 5759 4C41 57                          /CWYLAW
2005-09-29-11.33.35.149928-240 I105274C440        LEVEL: Error
PID     : 214958               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-291                APPID: *LOCAL.cwylaw.050929153332
FUNCTION: DB2 UDB, oper system services, sqlomkdirp, probe:20
MESSAGE : permissions:
DATA #1 : Hexdump, 4 bytes
0x2FF11E4C : 0000 01FD

从 db2diag.log 中可以看到,无法访问 /home/cwylaw/sqllib/function/jar/CWYLAW 目录。这是 JAR 文件的默认位置,其中的 CWYLAW 是这个例子中的实例名。现在,应该检查 /home/cwylaw/sqllib/function/jar/CWYLAW 目录上的权限,找到错误的设置。下面的例子显示 /function/jar 目录的读写权限已经被删除。要纠正这个问题,应该将权限改回默认设置:

清单 46. SQL1042 示例 1:纠正在安装 JAR 文件期间造成 SQL1042 的权限问题
cwylaw@bugdbug:/home/cwylaw/sqllib/function> ls -al | grep jar
d--x-wx--x   3 cwylaw   build           512 Sep 28 12:36 jar
cwylaw@bugdbug:/home/cwylaw/sqllib/function> chmod +rw jar
cwylaw@bugdbug:/home/cwylaw/sqllib/function> ls -al | grep jar
drwxrwxr-x  3 cwylaw   build           512 Sep 28 12:36 jar
cwylaw@bugdbug:/home/cwylaw/sqllib/function> db2 "call 
   sqlj.install_jar('file:/home/cwylaw/Out_20200.jar','OUT20200')"
DB20000I  The CALL command completed successfully.
清单 47. SQL1042 示例 2:不正确的 ASLHEAPSZ 和/或 QUERY_HEAP_SZ
cwylaw@bugdbug:/home/cwylaw> db2 "call out_language(?)"
SQL1042C  An unexpected system error occurred.  SQLSTATE=58004

查看 db2diag.log 中时间戳与问题发生的时间匹配的相关条目。

清单 48. SQL1042 示例 2:不正确的 ASLHEAPSZ 和/或 QUERY_HEAP_SZ。相关的 db2diag.log 条目
2005-09-28-23.09.01.831251-240 I32479C640         LEVEL: Error
PID     : 180988               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-16                 APPID: *LOCAL.cwylaw.050929030901
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:70
MESSAGE : Insufficient memory available for IPC communication with the 
          db2fmp process. Use the DB2_FMP_COMM_HEAPSZ registry variable 
          to adjust the amount of memory available for fenced routines.
DATA #1 : Hexdump, 4 bytes
0x2FF14260 : 0000 0000                                  ...
2005-09-28-23.09.01.837606-240 E33120C586         LEVEL: Error
PID     : 180988               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-16                 APPID: *LOCAL.cwylaw.050929030901
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:70
MESSAGE : ADM11002E  Insufficient shared memory available for 
          communication with the db2fmp process. Use the 
          DB2_FMP_COMM_HEAPSZ registry variable to increase the amount 
          of shared memory available for fenced routines.

2005-09-28-23.09.01.840540-240 I33707C493         LEVEL: Severe
PID     : 180988               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-16                 APPID: *LOCAL.cwylaw.050929030901
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:60
RETCODE : ZRC=0x8B0F003B=-1961951173=SQLO_NOMEM_UND
          "No memory available in 'Undefined Heap'"
          DIA8300C A memory heap error has occurred.

2005-09-28-23.09.01.893785-240 I34201C446         LEVEL: Severe
PID     : 180988               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-16                 APPID: *LOCAL.cwylaw.050929030901
FUNCTION: DB2 UDB, routine_infrastructure, sqlerAddFmpToPool, probe:20
MESSAGE : DiagData
DATA #1 : Hexdump, 4 bytes
0x2FF143F0 : FFFF FBEE                                  ...
2005-09-28-23.09.01.939694-240 I34648C640         LEVEL: Error
PID     : 180988               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-16                 APPID: *LOCAL.cwylaw.050929030901
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:70
MESSAGE : Insufficient memory available for IPC communication with the 
          db2fmp process. Use the DB2_FMP_COMM_HEAPSZ registry variable 
          to adjust the amount of memory available for fenced routines.
DATA #1 : Hexdump, 4 bytes
0x2FF14260 : 0000 0000                                  ...

注意,db2diag.log 指出内存不足,而且建议调整 DB2_FMP_COMM_HEAPSZ 变量。在开始调整任何当前设置之前,检查两个常常导致 SQL1042 错误的配置参数 ASLHEAPSZQUERY_HEAP_SZ

清单 49. SQL1042 示例 2:当出现 SQL1042 时的 ASLHEAPSZ 和 QUERY_HEAP_SZ 值
Application support layer heap size (4KB)   (ASLHEAPSZ) = 20000
Max requester I/O block size (bytes)         (RQRIOBLK) = 32767
Query heap size (4KB)                   (QUERY_HEAP_SZ) = 20000

ASLHEAPSZ 的默认值是 15,QUERY_HEAP_SZ 的默认值是 1000。评估这些值对于您的环境是否太高或者太低了。在大多数情况下,要么是 QUERY_HEAP_SZ 太低,致使 DB2 无法执行存储过程中的查询,要么是 ASLHEAPSZ 太高,致使没有足够的内存来分配大型 ASLHEAPSZ。在这个例子中,ASLHEAPSZ 太高,所以下面的例子将它降低到 2000。另外还将 QUERY_HEAP_SZ 降低到 2000,因为示例 OUT_LANGUAGE 存储过程只包含一个非常简单的查询。现在,存储过程成功运行了。

清单 50. SQL1042 示例 2:通过降低 ASLHEAPSZ 和 QUERY_HEAP_SZ 来纠正问题
cwylaw@bugdbug:/home/cwylaw> db2 update dbm cfg using ASLHEAPSZ 2000
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.
SQL1362W  One or more of the parameters submitted for immediate modification
were not changed dynamically. Client changes will not be effective until the
next time the application is started or the TERMINATE command has been issued.
Server changes will not be effective until the next DB2START command.
cwylaw@bugdbug:/home/cwylaw> db2 update dbm cfg using QUERY_HEAP_SZ 2000
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.
SQL1362W  One or more of the parameters submitted for immediate modification
were not changed dynamically. Client changes will not be effective until the
next time the application is started or the TERMINATE command has been issued.
Server changes will not be effective until the next DB2START command.
cwylaw@bugdbug:/home/cwylaw> db2stop
SQL1064N  DB2STOP processing was successful.
cwylaw@bugdbug:/home/cwylaw> db2start
SQL1063N  DB2START processing was successful.
cwylaw@bugdbug:/home/cwylaw> db2 connect to sample
   Database Connection Information
 Database server        = DB2/6000 8.2.3
 SQL authorization ID   = CWYLAW
 Local database alias   = SAMPLE
cwylaw@bugdbug:/home/cwylaw> db2 "call out_language(?)"
  Value of output parameters
  --------------------------
  Parameter Name  : LANGUAGE
  Parameter Value : JAVA
  Return Status = 0

如果将 DB2_FMP_COMM_HEAPSZ 设置为 0,那么也会发生 SQL1042 错误。这样的设置会阻止调用任何防护例程。

清单 51. SQL1042 示例 3:DB2_FMP_COMM_HEAPSZ=0。相关的 db2diag.log 条目
2005-09-28-23.26.05.803665-240 I88569C412         LEVEL: Warning
PID     : 184868               TID  : 1           PROC : db2sysc
INSTANCE: cwylaw               NODE : 000
FUNCTION: DB2 UDB, base sys utilities, sqleInitSysCtlr, probe:92
DATA #1 : String, 146 bytes
Warning! DB2_FMP_COMM_HEAPSZ is set to 0.
This means no fmps (including Health Monitor) and automatic
maintenance features of DB2 will be started.
...
2005-09-28-23.26.20.134728-240 I89996C486         LEVEL: Error
PID     : 180134               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-7                  APPID: *LOCAL.cwylaw.050929032612
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:65
MESSAGE : Can not run fenced routines (including Health Monitor) and 
          automatic maintenance features of DB2 because 
          DB2_FMP_COMM_HEAPSZ = 0.

2005-09-28-23.26.20.139210-240 E90483C515         LEVEL: Error
PID     : 180134               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-7                  APPID: *LOCAL.cwylaw.050929032612
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:65
MESSAGE : ADM11001E  DB2 did not create a memory segment for running 
          fenced routines. This was specified by the use of 
          DB2_FMP_COMM_HEAPSZ registry variable.
2005-09-28-23.26.20.142093-240 I90999C379         LEVEL: Severe
PID     : 180134               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-7                  APPID: *LOCAL.cwylaw.050929032612
FUNCTION: DB2 UDB, routine_infrastructure, sqlerGetFMPIPC, probe:8
RETCODE : ZRC=0x00000000=0=PSM_OK "Unknown"
2005-09-28-23.26.20.142601-240 I91379C446         LEVEL: Severe
PID     : 180134               TID  : 1           PROC : db2agent (SAMPLE)
INSTANCE: cwylaw               NODE : 000         DB   : SAMPLE
APPHDL  : 0-7                  APPID: *LOCAL.cwylaw.050929032612
FUNCTION: DB2 UDB, routine_infrastructure, sqlerAddFmpToPool, probe:20
MESSAGE : DiagData
DATA #1 : Hexdump, 4 bytes
0x2FF14410 : FFFF FBEE                                  ...

要纠正这个问题,可以将 DB2_FMP_COMM_HEAPSZ 设置为合适的值,或者不设置它(这样它会使用默认值)。

清单 52. SQL1042 示例 3:不正确的 DB2_FMP_COMM_HEAPSZ=0。纠正这个问题
cwylaw@bugdbug:/home/cwylaw> db2set -all
[i] DB2_FMP_COMM_HEAPSZ=0
[i] DB2COMM=TCPIP
[g] DB2SYSTEM=BUGDBUG
[g] DB2DBDFT=SAMPLE
[g] DB2COMM=TCPIP
[g] DB2ADMINSERVER=db2asv8
[g] DB2AUTOSTART=YES
cwylaw@bugdbug:/home/cwylaw> db2set DB2_FMP_COMM_HEAPSZ=
cwylaw@bugdbug:/home/cwylaw> db2set -all
[i] DB2COMM=TCPIP
[g] DB2SYSTEM=BUGDBUG
[g] DB2DBDFT=SAMPLE
[g] DB2COMM=TCPIP
[g] DB2ADMINSERVER=db2asv8
[g] DB2AUTOSTART=YES
cwylaw@bugdbug:/home/cwylaw> db2 terminate
DB20000I  The TERMINATE command completed successfully.
cwylaw@bugdbug:/home/cwylaw> db2stop
SQL1064N  DB2STOP processing was successful.
cwylaw@bugdbug:/home/cwylaw> db2start
SQL1063N  DB2START processing was successful.
cwylaw@bugdbug:/home/cwylaw> db2 connect to sample
   Database Connection Information
 Database server        = DB2/6000 8.2.3
 SQL authorization ID   = CWYLAW
 Local database alias   = SAMPLE
cwylaw@bugdbug:/home/cwylaw> db2 "call out_language(?)"
  Value of output parameters
  --------------------------
  Parameter Name  : LANGUAGE
  Parameter Value : JAVA
  Return Status = 0
cwylaw@bugdbug:/home/cwylaw>

SQL1131

清单 53. SQL1131 示例:Windows 上的 SQL1131.java
D:\>javac SQL1131.java
D:\>copy SQL1131.class "C:\Program Files\IBM\SQLLIB\Function"
        1 file(s) copied.
D:\>db2 -tvf Create.ddl
CREATE PROCEDURE SQL1131 (IN INPUT CHAR(10))
SPECIFIC SQL1131
DYNAMIC RESULT SETS 1
DETERMINISTIC
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
THREADSAFE
MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'SQL1131!abend'
;
DB20000I  The SQL command completed successfully.
D:\>db2 call SQL1131('Mgr')
SQL1131N  DARI (Stored Procedure) process has been terminated abnormally.
SQLSTATE=38503

这个操作失败并且显示 SQL1131N 错误。为什么呢?这可能有许多原因。ASLHEAPSZQUERY_HEAP_SZ 可能不够大,这两个配置参数是在数据库管理器配置文件中定义的。如果编写存储过程的方式使它所在的 JVM 终止,那么它也会抛出这个错误。为了判断非正常终止的原因,db2diag.log 有时包含有价值的信息,包括一个堆栈跟踪,其中包含 Java 存储过程最后执行的一系列调用,可以利用这些信息判断失败的原因。

在这个例子中,检查 Java 存储过程代码来找出问题。

清单 54. SQL1131 示例:SQL1131.java
1      //The simplest JAVA SP
2      import java.sql.*;
3  
4      public class SQL1131
5      {
6        public static void abend  (String input, ResultSet[] rsout) throws 
               SQLException, Exception
7        {
8
9              
10       int errorCode;
11
12       try
13       {
14         // get caller's connection to the database
15         Connection con = 
               DriverManager.getConnection("jdbc:default:connection");
16
17         String query = "SELECT * FROM STAFF WHERE JOB = ?";
18
19         PreparedStatement pstmt = con.prepareStatement(query);
20         pstmt.setString(1, input);
21         rsout[0] = pstmt.executeQuery();
22
23         java.lang.Runtime.getRuntime().exit(0);
24
25       }         
26       catch (SQLException sqle)
27       {
28         errorCode = sqle.getErrorCode();
29         throw new SQLException( errorCode + " FAILED" ); 
30       }
31
32       }
33     }

在上面的代码中,第 23 行将终止当前运行的 JVM,这会造成存储过程 “非正常终止”。可以看到,这是发生这种错误的明显例子(有点儿过度简化了)。要纠正这个问题,可以从上面的代码中删除第 23 行,重新编译存储过程,并且将新的类文件转移到 sqllib\function 文件夹。

清单 55. SQL1131 示例:纠正 SQL1131 错误
D:\>javac SQL1131.java
D:\>copy SQL1131.class "C:\Program Files\IBM\SQLLIB\Function"
Overwrite C:\Program Fils\IBM\SQLLIB\Function\SQL1131.class? (Yes/No/All): Y
        1 file(s) copied.
D:\>db2 call SQL1131('Mgr')
  Result set 1
  --------------
  ID     NAME      DEPT   JOB   YEARS  SALARY    COMM
  ------ --------- ------ ----- ------ --------- ---------
      10 Sanders       20 Mgr        7  18357.50         -
      30 Marenghi      38 Mgr        5  17506.75         -
      50 Hanes         15 Mgr       10  20659.80         -
     100 Plotz         42 Mgr        7  18352.80         -
     140 Fraye         51 Mgr        6  21150.00         -
     160 Molinare      10 Mgr        7  22959.20         -
     210 Lu            10 Mgr       10  20010.00         -
     240 Daniels       10 Mgr        5  19260.25         -
     260 Jones         10 Mgr       12  21234.00         -
     270 Lea           66 Mgr        9  18555.50         -
     290 Quill         84 Mgr       10  19818.00         -
  11 record(s) selected.
  Return Status = 0

致谢

特别感谢 Stephanie Kivell(IBM DB2 Premium Support)提供输入并且审阅了本文。

更多的信息

在开发 Java 存储过程期间,您可能会遇到上述的问题。我们的意图不是教您如何编写 Java 例程,而是帮助您解决常见的 Java 例程问题。我们希望您在阅读本文之后能够解决大部分问题。如果在尝试了本文中给出的建议之后,仍然无法纠正问题,那么可能是遇到了更复杂的情况。在这种情况下,应该与 IBM DB2 支持人员联系,我们会进一步帮助您。如果需要关于如何编写 Java 存储过程的信息,应该参考 Application Developement Guide,这可以从以下网址获得:

http://www-306.ibm.com/software/data/db2/udb/support/manualsv8.html


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=98637
ArticleTitle=解决 DB2 UDB Java 存储过程的常见问题
publish-date=11102005