- 追加された行はこの色です。
- 削除された行はこの色です。
** PLSQLでBLOBデータを扱う([[Oracle>Oracleメモ]]) [#e64bcbee]
#setlinebreak(on);
【ファイルから登録】
set serveroutput on
declare
v_blob_locater blob;
v_handle bfile := bfilename('LOB_DATA_PATH', 'test.jpg');
v_amount pls_integer;
v_doffset pls_integer := 1;
v_soffset pls_integer := 1;
begin
dbms_lob.fileopen(v_handle, dbms_lob.file_readonly);
v_amount := dbms_lob.getlength(v_handle);
insert into test_blob_data (
id,
data
) values (
seq_test_blob_data.nextval,
empty_blob()
) returning data into v_blob_locater;
dbms_lob.loadblobfromfile(
v_blob_locater,
v_handle,
v_amount,
v_doffset,
v_soffset
);
dbms_output.put_line ( '書き込まれたサイズ : ' || v_doffset || 'Bytes' );
commit;
dbms_lob.fileclose(v_handle);
end;
/
【ファイルへ読み込み】
set serveroutput on
declare
v_blob_locater blob;
v_offset integer := 1;
v_buffer long raw;
v_file_buffer_size integer := 32000;
v_amount integer := 32000;
v_totalsize integer;
v_filetype utl_file.file_type;
v_filename varchar2(1000) := 'maguro_out.jpg';
v_openmode varchar(2) := 'wb';
begin
select data into v_blob_locater
from test_blob_data where id = 1;
v_totalsize := dbms_lob.getlength(v_blob_locater);
v_filetype := utl_file.fopen(
'LOB_DATA_PATH',
v_filename,
v_openmode,
v_file_buffer_size
);
while v_offset < v_totalsize loop
if v_offset + v_amount > v_totalsize then
v_amount := v_totalsize - v_offset + 1;
end if;
dbms_lob.read(
v_blob_locater,
v_amount,
v_offset,
v_buffer
);
utl_file.put_raw(
v_filetype,
v_buffer,
true
);
v_offset := v_offset + v_amount;
dbms_output.put_line ( 'Offset : ' || v_offset );
end loop;
utl_file.fflush(v_filetype);
utl_file.fclose(v_filetype);
end;
/
【blobからclobへ変換するFUNCTION】
/*
* UTL_RAWなどを使用してBLOBをVARCHAR2に変換すると32K(VARCHAR2の最大長?)以上のデータを
* 扱えない(エラーになる)為、CLOB<->BLOBの変換を行う独自関数を作成する(パクッったけど..)
*/
CREATE OR REPLACE FUNCTION blob2clob (
p_blob IN BLOB DEFAULT EMPTY_BLOB ( )
, p_success OUT VARCHAR2 )
RETURN CLOB
IS
bdoc BLOB := p_blob;
cdoc CLOB := EMPTY_CLOB ( );
document CLOB := EMPTY_CLOB ( );
lob_id NUMBER;
amount NUMBER;
bdoc_size NUMBER;
BLOCK NUMBER := 10000;
blockcount NUMBER;
rawbuff RAW ( 32000 );
pos NUMBER;
charbuff VARCHAR2 ( 32000 );
charbuff_size NUMBER;
BEGIN
dbms_lob.createtemporary ( cdoc,TRUE,dbms_lob.CALL );
bdoc_size := dbms_lob.getlength ( bdoc );
IF BLOCK < bdoc_size THEN
blockcount := ROUND ( ( bdoc_size / BLOCK ) + 0.5 );
ELSE
blockcount := 1;
END IF;
pos := 1;
FOR i IN 1 .. blockcount LOOP
dbms_lob.READ ( bdoc,BLOCK,pos,rawbuff );
charbuff := utl_raw.cast_to_varchar2 ( rawbuff );
charbuff_size := LENGTH ( charbuff );
dbms_lob.writeappend ( cdoc,charbuff_size,charbuff );
pos := pos + BLOCK;
END LOOP;
p_success := 'OK';
RETURN cdoc;
EXCEPTION
WHEN OTHERS
THEN
p_success := 'ERROR::' || SQLCODE || ' -' || SQLERRM;
RETURN EMPTY_CLOB ( );
END blob2clob;
【clobからblobへ変換するFUNCTION】
/*
* UTL_RAWなどを使用してBLOBをVARCHAR2に変換すると32K(VARCHAR2の最大長?)以上のデータを
* 扱えない(エラーになる)為、CLOB<->BLOBの変換を行う独自関数を作成する(パクッったけど..)
*/
create or replace function clob2blob(p_clob clob) return blob as
v_blob blob;
v_str varchar2(32767);
v_offset integer := 1;
v_length integer;
v_sum integer;
begin
dbms_lob.createTemporary(v_blob, false, dbms_lob.SESSION);
v_length := dbms_lob.getLength(p_clob);
loop
v_sum := 32767;
dbms_lob.read(p_clob, v_sum, v_offset, v_str);
dbms_lob.writeAppend(v_blob, v_sum, utl_raw.cast_to_raw(v_str));
exit when v_offset + v_sum >= v_length;
v_offset := v_offset + v_sum;
end loop;
return v_blob;
end;
/