分享

利用UDF来调用操作系统命令和DB2的常用命令

 WindySky 2010-10-13
2010-07-22 10:38

      由于DB2是不支持复合 SQL 语句内不支持调用操作系统命令,所以一些对应我们常用的一些语句如数据导入,导出是命令行而不是SQL语句,都不能在存储过程中调用,必须写一些SHELL或者BAT文件,进行脚本编制来进行。 但是在我们的这种BI应用中,ETL过程中的E过程,数据的导入是一件必不可少的过程,通过脚本的控制,比较麻烦和整个过程有点不是很完整。 找寻是否有其他的解决方案。不过据说在新版本的DB2上是可以支持的。但是我们都是用V8.1
     之前看了IBM网站的一篇文章,提到可以利用 UDF 来执行纯 SQL 中不可用的操作。因为UDF可以用外部语言(即,SQL 以外的其它语言,如JAVA,C)编写,并可以通过使用 CREATE 语句向数据库注册,这样我们就可以编写一个JAVA应用程序来调用操作系统命令和DB2的常用命令。 当这个外部函数注册后,
我们就可以在存储过程中可以使用该函数,进行数据的导入,导出。
参见资料“另一篇有关高级脚本编制的文章”和“如何注册Java UDF ”

步骤:
1、编写一个JAVA程序(os_cmdUDF.java)
import java.io.*;
import COM.ibm.db2.app.UDF;

public class os_cmdUDF extends UDF{
    public static int os_cmd(String cmd) {
        Runtime rt = Runtime.getRuntime();
        Process p=null;
        int success = 0;
        try {
            p = rt.exec(cmd);
        }
        catch (IOException e) {
            success = -1;
        }
        return (success);
    }
}

2、运行javac UDFLogs.java编译
javac os_cmdUDF.java

产生的结果是一个称为 os_cmdUDF.class 的文件,
随后需要将该 .class 文件复制到 sqllib\ 目录

3、运行jar打包UDFLogs.class为os_cmdUDF.jar
jar cf os_cmdUDF.jar os_cmdUDF.class

4、连上数据库,运行安装.jar文件到数据库
db2 connect to testsu user db2admin
db2 "CALL sqlj.install_jar('D:\IBM\SQLLIB\java\jdk\bin\os_cmdUDF.jar', 'os_cmdUDF')"

之后os_cmdUDF.jar安装到D:\IBM\SQLLIB\\jar\DB2ADMIN\的路径下。

5、运行create 建立函数
DROP os_cmd;
CREATE os_cmd( IN VARCHAR(1000))
RETURNS INTEGER
EXTERNAL NAME 'os_cmdUDF:os_cmdUDF!os_cmd'
LANGUAGE JAVA
PARAMETER STYLE JAVA
NOT DETERMINISTIC
NO SQL
EXTERNAL ACTION
;

6、测试os_cmd函数是否可用
db2 "values os_cmdUDF('db2cmd.exe')"
返回结果,
1
-----------
          0

1 条记录已选择。

函数可以用。

7、建立调用os_cmd函数的存储过程。
CREATE PROCEDURE DB2ADMIN.sp_exec(
--输入参数
IN loadstr varchar(1024),
--输出参数
OUT o_err_msg varchar(1024)
)
--支持语言
LANGUAGE SQL

P1: BEGIN
--临时变量,出错变量
declare SQLCODE          integer default 0;
declare stmt             varchar(1024);
declare state            varchar(1024) default 'AAA';--记录程序当前所作工作
DECLARE status INT DEFAULT 0;

--声明出错处理
DECLARE EXIT HANDLER FOR SQLEXCEPTION
begin
    set o_err_msg='处理'||state||'出错 '||'错误代码SQLCODE:'||CHAR(SQLCODE);
end;

--程序开始
SET status = os_cmd(loadstr );
if (status <> 0) then
set o_err_msg = stmt;
end if ;

END P1                                                              

8、调用存储过程
call sp_exec('db2cmd.exe E:\work_file\济南商行\测试\DB2测试\DBCONN_space.bat');

DBCONN_export.bat的作用(清空一个表):
DB2 CONNECT TO testsu USER db2admin using db2admin/
db2 "load from 'E:\work_file\济南商行\测试\DB2测试\space.dat' OF DEL MODIFIED BY NOROWWARNINGS MESSAGES 'E:\work_file\济南商行\测试\DB2测试\space.log' REPLACE INTO jxdx_ckzhmx "
DB2 CONNECT RESET

9、验证存储过程调用的结果。
db2 select count(*) from jxdx_ckzhmx


注意:在测试这个功能的时候有一些细节没有注意,导致函数注册后不能调用。
1、编译JAVA源文件的编译器和执行的JVM的版本必须一致的
DB2 V8.2 安装时带的 "1.4.1";
而本机又另外装了一个 "1.5.0_05"
之前没有注意,直接使用命令javac来进行编译,用的是默认1。5版本的
函数注册后,调用出错,提示SQL4304 reason code "1"的错误信息;
而给出的提示是说CLASSPATH 有问题,所以注意力一直放到这个方面找问题所在
后来才发现真正的问题是出现在版本上。
最好直接在\SQLLIB\java\jdk\bin的目录下编译后再COPY。

2、设置 Java 环境
几个关键的设置:
参见文档:《解决 DB2 UDB Java 存储过程的常见问题》
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 页)。

其他相关内容:
一、如何安装jar文件到当前数据库:
db2 "CALL sqlj.install_jar('D:\IBM\SQLLIB\java\jdk\bin\os_cmdUDF.jar', 'os_cmdUDF')"

二、如何更新当前数据库中的jar文件:
db2 "CALL sqlj.remove_jar('os_cmdUDF')"

三、如何替换当前数据库中删除jar文件:
db2 "CALL sqlj.replace_jar('D:\IBM\SQLLIB\java\jdk\bin\os_cmdUDF.jar', 'os_cmdUDF')"

四、如何当前数据库中删除jar文件:
db2 "CALL sqlj.remove_jar('os_cmdUDF')"

五、如何刷新已经调用的jar或class,不用重启实例就生效:
db2 "CALL SQLJ.REFRESH_CLASSES()"

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多