PL/SQL以外のストアドプロシージャ その4
Javaストアドプロシージャを使ってDatabaseの外(サーバ機そのもの)のリソースにアクセスする方法です。
PL/SQLはデータベース内データを扱う事には長けていますが、それ以外のファイルアクセスとかはとても苦手です。あるディレクトリに「どんなファイルがあるか」を調べる事すら出来ません。また、外部プログラムを起動することもできません。
今回は下記のJavaクラスメソッドを使ってOSのコマンドプロンプトを起動、dirコマンド等を発行してみます。Java(JVM)から他のプログラムを呼ぶには標準ライブラリの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というわけです。 サーバ上のエクスプローラで確認するとちゃんとファイルができてますよ。 アイディアしだいでどんな実装も可能です。