Skip to content

Instantly share code, notes, and snippets.

@seraphy
Created December 22, 2011 08:17
Show Gist options
  • Save seraphy/1509490 to your computer and use it in GitHub Desktop.
Save seraphy/1509490 to your computer and use it in GitHub Desktop.
Oracleの一時LOBを、32KBを超えるバイナリデータ用の一時バッファとして使い、それを区切りのよい単位てBASE64でファイル出力するサンプル
declare
-- 32Kを超えるバイナリデータをBLOB上に作成する
procedure generate_message(lb in out nocopy blob, cnt number) is
mes varchar2(4096);
rd raw(4096);
begin
for idx in 1..cnt
loop
mes := 'メッセージNo. ' || to_char(idx) || chr(10);
rd := UTL_I18N.STRING_TO_RAW(mes, 'UTF8');
DBMS_LOB.WRITEAPPEND(lb, UTL_RAW.LENGTH(rd), rd);
end loop;
end;
-- BLOBから48バイトづつ取り出しBASE64に変換し
-- 1行64文字でファイルに出力する
procedure write_file(lb in out nocopy blob) is
vHandle UTL_FILE.FILE_TYPE;
amount BINARY_INTEGER := 768; -- 48の倍数 (3と4で割り切れる数の1行単位);
pos pls_integer := 1;
blob_len pls_integer := dbms_lob.getlength(lb);
buf raw(1152); -- BASE64変換後のサイズ(読み込みバイトの1.5倍)
begin
vHANDLE := UTL_FILE.FOPEN('TEMP_DIR', 'data.txt', 'wb');
-- 48バイトで端数なしで出力できるBASE64の1行の最大桁.
-- その倍数単位のバッファでループを回す.
WHILE pos < blob_len
LOOP
DBMS_LOB.READ(lb, amount, pos, buf);
UTL_FILE.PUT_RAW(
vHANDLE,
UTL_ENCODE.BASE64_ENCODE(buf), -- 自動で改行コードが入る
TRUE
);
buf := NULL;
pos := pos + amount;
END LOOP;
UTL_FILE.FCLOSE(vHANDLE);
EXCEPTION WHEN OTHERS THEN
UTL_FILE.FCLOSE(vHANDLE);
RAISE;
end;
begin
declare
lb blob;
st timestamp;
en timestamp;
begin
-- 一時BLOBを構築、寿命を呼び出しスコープに設定
DBMS_LOB.CREATETEMPORARY(lb, TRUE, DBMS_LOB.CALL);
-- 32Kを超えるデータを作成
generate_message(lb, 23456);
-- 長さの検証
st := systimestamp;
dbms_output.put_line('len=' || dbms_lob.getlength(lb) || '/' || st);
-- ファイルにBASE64として書き出し
write_file(lb);
en := systimestamp;
dbms_output.put_line(en || '/span=' || (en - st));
-- 一時LOBの破棄
DBMS_LOB.FREETEMPORARY(lb);
end;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment