c:\Users\じぶん

技術ネタ半分、日記半分ですかね。

PL/SQL以外のストアドプロシージャ その4

Javaストアドプロシージャを使ってDatabaseの外(サーバ機そのもの)のリソースにアクセスする方法です。

PL/SQLはデータベース内データを扱う事には長けていますが、それ以外のファイルアクセスとかはとても苦手です。あるディレクトリに「どんなファイルがあるか」を調べる事すら出来ません。また、外部プログラムを起動することもできません。

今回は下記のJavaクラスメソッドを使ってOSのコマンドプロンプトを起動、dirコマンド等を発行してみます。JavaJVM)から他のプログラムを呼ぶには標準ライブラリのRuntimeやProcessを使います。(SystemJava.java)

public class SystemJava {
        public static int cmdRun(String args)  {
            try {
                Runtime r = Runtime.getRuntime();
                Process p = r.exec("cmd /c \"" + args + "\"");
                int errorLevel = p.waitFor();
                return errorLevel;
            } catch (Exception ex) {
                System.err.println(ex.getMessage());
                return 255;
            }
    }
}

SystemJavaクラスと任意の文字列を引数とするcmdRunメソッドです。 execで外部プログラムを実行できますが、コマンドプロンプトを介して実行できるようにcmdに渡す文字列として引数を利用します。こうすることでdirコマンドなども実行できます。

さらに、実行後に戻り値(ERRORLEVEL環境変数)を返すことにして、もし何らかの例外が起きたら戻り値255として終了することにします。

Oracle Databaseへの登録は…

loadjava -user DBUSER/DBPASS@ORCL SystemJava.java

となります。 紐付けるファンクションは、数値を返すRUNファンクション

CREATE OR REPLACE FUNCTION RUN ( args VARCHAR2 ) RETURN NUMBER
  AS LANGUAGE JAVA
  NAME 'SystemJava.cmdRun( java.lang.String ) return int';
/

としました。文字列が引数で、戻り値が数値ですね! で…このままだと実行権限が不足してしまうので、以下のコマンドをSQL*PLUSで流します。

dbms_java.grant_permission( 'DBUSER', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )

↑はお決まりです。実行権限不足のエラーメッセージにこのコマンドそのものが 記載されますので、「そういうもの」と思って実行しましょう。

これで準備は整いました、まずは戻り値を見るためにexitコマンドから…

SQL> select run('exit /b 123') from dual;

RUN('EXIT/B123')
----------------
             123

「EXIT /B [戻り値]」なので、123がそのまま戻り値になってます。 問題なさそうですね、引き続きdirコマンドいきます。

SQL> select run('dir d:\ >c:\dir_d.txt') from dual;

RUN('DIRD:\>C:\DIR_D.TXT')
--------------------------
                         0

SQL>

実行結果をリダイレクトしてc:\dir_d.txtというファイルに書き込んでいます。 正常に書き込みできているので戻り値は0というわけです。 サーバ上のエクスプローラで確認するとちゃんとファイルができてますよ。 アイディアしだいでどんな実装も可能です。