では、逆にLOBデータをファイルに直接出力するにはどうすればいいのでしょうか?
DBMS_LOBパッケージにはLOBデータをファイルに直接出力するプロシージャはなぜか用意されていません。
そこでDBMS_LOBパッケージに代わる方法としてJavaストアドプロシージャを利用する方法のみを説明します。
※ここではBLOBデータを例に説明します。
JavaストアドプロシージャでLOBデータをファイルに直接出力する場合、まず、BLOBデータを読み込んでファイルに出力するメソッドを持つJavaのクラスを用意します。
package orcl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import oracle.sql.BLOB;
public class UtlLob {
public static long downLoadBlob( BLOB blob, String dirName, String fileName ) {
File dir = null;
File file = null;
FileOutputStream fos = null;
InputStream ins = null;
try {
//ディレクトリのFileオブジェクトを生成します。
dir = new File( dirName );
//ディレクトリが存在しない場合、終了します。(失敗)
if( !dir.exists() ) {
return -1L;
}
//出力ファイルのFileオブジェクトを生成します。
file = new File( dir, fileName );
//出力ファイルへの出力ストリームを生成します。
fos = new FileOutputStream( file );
//BLOBファイルの入力ストリームを生成します。
ins = blob.getBinaryStream();
//BLOBデータの読み込みに最適なバッファ・サイズを算出し、バッファを生成します。
byte[] buffer = new byte[ blob.getChunkSize() ];
//BLOBデータが空の場合、終了します。
if( ins == null ){
return 0;
}
else {
//バッファ・サイズ単位でBLOBデータを読み込み、出力ファイルに書き込みます。
int length = -1;
while( ( length = ins.read( buffer ) ) != -1 ) {
fos.write( buffer , 0 , length );
}
}
return blob.length();
} catch (Exception e) {
e.printStackTrace();
return -1L;
} finally {
try { ins.close(); } catch( Exception ignore ) {}
try { fos.close(); } catch( Exception ignore ) {}
}
}
}
このJavaクラスでは、BLOBロケータ、ディレクトリ名、ファイル名を引数として受け取り、指定されたBLOBロケータからBLOBデータを読み込んで指定されたファイルに流し込んでいます。
そして、このJavaクラスをCREATE JAVA文を使ってOracleにロードし、以下のような呼び出しの仕様(コール・スペック)を定義します。
CREATE OR REPLACE FUNCTION UTLLOB_DOWNLOADBLOB_FUNC ( p_blob BLOB, p_dir VARCHAR2, p_file VARCHAR2 ) RETURN NUMBER AS LANGUAGE JAVA NAME 'orcl.UtlLob.downLoadBlob( oracle.sql.BLOB, java.lang.String, java.lang.String ) return long'; /
そして、このJavaクラスがファイルにアクセスできるようJAVAのセキュリティを設定する。
CALL dbms_java.grant_permission( 'SCOTT', 'SYS:java.io.FilePermission', '<>', 'read' ) / CALL dbms_java.grant_permission( 'SCOTT', 'SYS:java.io.FilePermission', '< >', 'write' ) / CALL dbms_java.grant_permission( 'SCOTT', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '' ) / CALL dbms_java.grant_permission( 'SCOTT', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '' ) /
以上でようやくファイルにアクセスするJavaストアロプロシージャが準備ができたことになります。
このJavaストアドプロシージャを利用して、BLOBデータをファイルに直接出力するには以下のような手順をとります。
DECLARE
wk_blob BLOB; --BLOBロケータ
wk_length NUMBER(38); --BFILEロケータ
BEGIN
--BLOBロケータ取得
SELECT COL3 INTO wk_blob
FROM TABLEA
WHERE COL1 = 1;
--ファイルをBLOBロケータにロード
wk_length := UTLLOB_DOWNLOADBLOB_FUNC( wk_blob, 'C:\\Temp', 'TEST.DAT' );
END;
/
ご覧の通り、Javaストアドプロシージャさえ準備できれば、あとはSELECT文で出力するBLOBデータのBLOBロケータを取得し、Javaストアドプロシージャを呼び出すだけ。
非常に簡単です。
【関連エントリ】
[Oracle] LOBデータの基本的な扱い方 2004/12/03
[Oracle] JDBCによるLOBの操作方法 2004/12/06
[Oracle] LOBデータをファイルから直接登録する方法(その1) 2005/01/25
[Oracle] LOBデータをファイルから直接登録する方法(その2) 2005/01/27
[Oracle] LOBデータをファイルに直接出力する方法 2005/02/01
[Oracle] JavaでLOBデータを読み込む際の最適なバッファサイズは? 2005/02/02
[Oracle] LOB記憶特性 その1(STORAGE IN ROW) 2005/08/23
[Oracle] LOB記憶特性 その2(CHUNK) 2005/08/24