次に、Oracleに格納されているデータファイルをPL/SQLでOS上のファイルに書き出すサンプルを作ってみます。
1 set serveroutput on 2 declare 3 v_blob_locater blob; 4 v_offset integer := 1; 5 v_buffer long raw; 6 7 v_file_buffer_size integer := 32000; 8 v_amount integer := 32000; 9 10 v_totalsize integer; 11 v_filetype utl_file.file_type; 12 v_filename varchar2(1000) := 'maguro_out.jpg'; 13 v_openmode varchar2(2) := 'wb'; 14 15 begin 16 select data into v_blob_locater from test_blob_data where id = 1; 17 v_totalsize := dbms_lob.getlength(v_blob_locater); 18 v_filetype := utl_file.fopen( 'LOB_DATA_PATH', v_filename, v_openmode, 19 v_file_buffer_size ); 20 21 while v_offset < v_totalsize loop 22 if v_offset + v_amount > v_totalsize then 23 v_amount := v_totalsize - v_offset + 1; 24 end if; 25 dbms_lob.read( 26 v_blob_locater, 27 v_amount, 28 v_offset, 29 v_buffer 30 ); 31 32 utl_file.put_raw( 33 v_filetype, 34 v_buffer, 35 true 36 ); 37 v_offset := v_offset + v_amount; 38 dbms_output.put_line ( 'Offset : ' || v_offset ); 39 end loop; 40 41 utl_file.fflush(v_filetype); 42 utl_file.fclose(v_filetype); 43 44 end; 45 /
前ページのデータ格納で使用したテーブルとデータを使用しています。では、こちらも順を追って解説します。
5行目
バッファデータをLONG RAW型で宣言しています。バイナリデータですので、RAWデータが使用されています。
7行目
UTL_FILE.PUT_RAWサブプログラムのバッファサイズの上限は32767bytesです。そのため、今回は32000bytesを上限として、書き出しを行います。
11行目
utl_file.file_type型の変数を定義します。これが出力するファイルのファイルIDとなります。
13行目
openmodeには、バイナリデータを書き込むwbを指定します。
16行目
SELECT文で、ID=1のレコードのBLOBデータを抽出しています。検索されたBLOBロケータをv_blob_locaterに代入し、この後のDBMS_LOB.READで使用します。
17行目
UTL_FILE.PUT_RAWの制限(32767bytesまでのバッファ)をクリアするために、ループしながらLOBの読み込みとファイルへの書き出しを行います。そのため、Max値としてDBMS_LOB.GETLENGTHで、対象LOBデータのMAXサイズを取得します。
18行目
UTL_FILE.FOPENでファイルをオープンします。UTL_FILE.FOPENの引数は以下のとおりです。
location IN VARCHAR2
VARCHAR2となっていますが、Create Directoryで作成したDirectoryオブジェクトを指定することも可能です。ここに指定するPATHは、今回のようにCreate Directoryで作成したDirectoryオブジェクトか、初期化パラメータファイルのutl_file_dirで指定されたPATHのみが使用できます。
filename IN VARCHAR2
出力するファイル名を指定します。
open_mode IN VARCHAR2
オープンするモードを指定します。
r…テキストの読込み
w…テキストの書込み
a…テキストの追加
rb…バイト(バイナリ)の読込み
wb…バイト(バイナリ)の書込み
ab…バイト(バイナリ)の追加
max_linesize IN BINARY_INTEGER
BLOBデータの場合は、バイナリデータであるため最大バッファの値ということになります。最大は32767bytesで、デフォルトでは1000bytesになります。
20行目
v_amountで指定したbytes分ずつLOBの読み取りとファイルへの書き出しをv_totalsizeまで繰り返し行います。21〜23行目では、v_totalsizeを上回ってしまった場合(データのEOF)に、全体から書き込みを行ったサイズを引いて、残りのamountを算出します。また、offsetは1からスタートしているので、最後の1byteを取得するために1を加算しています。
24行目
SELECT文で取得したBLOBロケータから実データを読み込みます。DBMS_LOB.READの引数は以下のとおりです。
lob_loc IN BLOB
読み込み対象のBLOBロケータを指定します。
amount IN OUT NOCOPY BINARY_INTEGER
読み取りサイズを指定します。offsetで指定した開始位置からamount分のデータを読み込みます。
offset IN INTEGER
読み取り開始位置を指定します。
buffer OUT RAW
読み取ったデータを格納するバッファを指定します。
サンプルの例では、BLOBロケータで示されるBLOBデータをv_offset目からv_amount分読み込んで、v_buffer変数に格納という指定になります。
31行目
24行目で取得したBLOBデータをUTL_FILE.PUT_RAWサブプログラムでファイルに書き出しています。3番目の引数(autoflash)をtrueに設定することで、書き込みバッファを自動的にフラッシュし物理ディスクに記録してくれます。
以上でBLOBデータの格納と出力を行うことができます。実際の現場ではPL/SQLのみで行うケースは、あまりないかもしれませんが開発機などでBLOBの動作を確認したいときなどにすぐ使えると思いますので、ぜひマスターしてくださいね。(次回に続く)
Oracleに特化した製品開発、コンサルティングを手掛けるエンジニア集団。大道隆久は緊迫したトラブル現場でも常に冷静沈着であり、スマートに解決へと導いていくシステムコンサルタント。
Copyright © ITmedia, Inc. All Rights Reserved.