** PLSQLでBLOBデータを扱う(Oracle) [#e64bcbee]
** 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;
 /

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS