Выбрать главу

) AS

v _ s rc_ c lo b CLOB;

v _ f ile UTL_FILE.FILE_TYPE;

v _ o ffs e t INTEGER := 1;

v_amount INTEGER := 32767;

v _ ch a r_ b u ffe r VARCHAR2(32767);

BEGIN

- получим локатор LOB для CLOB

SELECT clob_column

INTO v _ src_ c lo b

FROM clob _con te n t

WHERE id = p_clob_id;

- откроем файл для записи текста (вплоть до v_amount символов за один

раз)

v _ f ile := UTL_FILE.FOPEN( p _ d ire c to гу, p_file_name, w , v_amount);

- скопируем данные из v _ s rc_ c lo b в файл

LOOP

BEGIN

- прочитаем символы из v _ s rc_ c lo b в v _ ch a r_ b u ffe r

DBMS_L0B.READ(v_src_clob, v_amount, v _ o ffs e t, v _ c h a r_ b u ffe r);

- скопируем символы из v _ ch a r_ b u ffe r в файл

UTL_F ILE.PUT (v_file, v _ c h a r_ b u ffe r);

- добавим v_amount к v _ o ffs e t

v _ o ffs e t := v _ o ffs e t + v_amount;

EXCEPTION

- выйти, если в файле нет больше данных

WHEN N0_DATA_F0UND THEN

EXIT;

END;

END LOOP;

- запишем оставшиеся данные в файл

UTL_FILE. FFLUSH(v _ f i l e ) ;

- закроем файл

UT L_F ILE .FC LO S E (v_ file );

DBMS_OUTPUT.PUT_LINE('Copy s u c c e s s fu lly com p le te d .');

END co p y _ c lo b _ d a ta _ to _ file ;

/

Следующий пример вызывает c o p y _ c lo b _ d a ta _ to _ file ( ) для копирования

содержимого CLOB #3 в новый файл по имени textContent2.txt:

□ CALL c o p y _ c lo b _ d a ta _ to _ file (3 , ' SAMPLE_FILES_DIR', 'te x tC o n te n t2 .tx t );

Copy s u c c e s s fu lly completed.

Если вы посмотрите папку C:\sample_files, то обнаружите там новый

файл textContent2.txt. Этот файл содержит текст, идентичный тексту

textContent.txt.

Большие объекты 533

Следующая процедура copy_blob_data_to_file() показывает, как читать

двоичные данные из BLOB и сохранять их в файл:

П CREATE PROCEDURE copy_blob_data_to_file(

p_blob_id INTEGER,

p_directory VARCHAR2,

p_file_name VARCHAR2

) AS

v_src_blob BLOB;

v _ f ile UTL_FILE.FILE_TYPE;

v_offset INTEGER := 1;

v_amount INTEGER := 32767;

v_binary_buffer RAW(32767);

BEGIN

- получим локатор LOB для BLOB

SELECT blob_column

INTO v_src_blob

FROM blob_content

WHERE id = p_blob_id;

- откроем файл для записи байтов (вплоть до v_amount байтов за одну

операцию) _ -

v _ f ile := UTL_FILE.FOPEN( p_directory, p_file_name, 'wb', v_amount);

- скопируем данные из v_src_blob в файл

LOOP

BEGIN

- прочитаем символы из v_src_blob в v_binary_buffer

DBMS_L0B.READ(v_src_blob, v_amount, v_offset, v_binary_buffer);

- скопируем двоичные данные из v_binary_buffer в файл

UTL_FILE.PUT_RAW(v_file, v_binary_buffer);

- добавим v_amount к v_offset

v_offset := v_offset + v_amount;

EXCEPTION

- выйти, если в файле больше нет данных

WHEN N0_DATA_F0UND THEN

EXIT;

END;

END LOOP;

- запишем любые оставшиеся данные в файл

UTL_FILE.FFLUSH( v _ f i le );

- close the f i l e

UTL_FILE.FCL0SE(v_file);

DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');

END copy_blob_data_to_file;

/

Следующий пример вызывает copy_blob_data_to_file() для копирования

содержимого BLOB #3 в новый файл по имени binaryContent2.doc:

□ CALL copy_blob_data_to_file(3, ' SAMPLE_FILES_DIR', ' binaryContent2.

d o c');

Copy successfully completed.

Если вы посмотрите папку C:\sample_files, вы обнаружите там новый

файл binaryContent2 .doc. Этот файл содержит информацию, идентичную

binaryContent.doc.

534 Глава 14

Разумеется, copy_blob_data_to_file() можно использовать для записи

любых двоичных данных, содержащихся в BLOB, в файл. Двоичные данные

могут содержать музыку, видео, изображения, исполняемые файлы и т.п.

Копирование данных из B F ILE в C LO B и B LO B

Следующая процедура copy_bfile_data_to_clob() показывает, как читать

текст из BFILE и сохранять его в CL0B:

□ CREATE PROCEDURE copy_bfile_data_to_clob(

p_bfile_id INTEGER,

p_clob_id INTEGER

) AS

v_src_bfile BFILE;

v_directory VARCHAR2(200);

v_filename VARCHAR2(200);

v_length INTEGER;

v_dest_clob CLOB;

v_amount INTEGER := DBMS_L0B.LOBMAXSIZE;

v_dest_offset INTEGER := 1;

v_src_offset INTEGER := 1;

v_src_csid INTEGER := DBMS_L0B.DEFAULT_CSID;

v_lang_context INTEGER := DBMS_L0B.DEFAULT_LANG_CTX;

v_warning INTEGER;

BEGIN

- получим локатор для BFILE

SELECT bfile_column

INTO v_src_bfile

FROM bfile_content

WHERE id = p_bfile_id;

- используем FILEEXISTSO для проверки существования файла

- (FILEEXISTSO возвращает 1, если файл существует)

IF (DBMS_L0B.FILEEXISTSCv_src_bflie) = 1) THEN

- используем 0PEN(), чтобы открыть файл

DBMS_L0B.0PEN(v_src_bfile);

- используем FILEGETNAME(), чтобы получить имя файла и каталога

DBMS_L0B.FILEGETNAME(v_src_bfile, v_directory, v_filename);

DBMS_OUTPUT.PUT_LINE('Directory = ' || v_directory);

DBMS_OUTPUT.PUT_LINE('Filename = ' || v_filename);

- добавим пустой CLOB

INSERT INTO clob_content(

id, clob_column

) VALUES (

p_clob_id, EMPTY_CLOB()

- получим локатор LOB для CLOB (для обновления)

SELECT clob_column

INTO v_dest_clob

FROM clob_content

WHERE id = p_clob_id

FOR UPDATE;

- используем L0ADCL0BFR0MFILE(), чтобы получить до v_amount символов

- из v_src_bfile и сохраняем их в v_dest_clob, начиная со

Большие объекты 535

- смещения o ffse t 1 в v_src_bfile и v_dest_clob

DBMS_L0B.L0ADCL0BFR0MFILE(

v_dest_clob, v_src_bfile,

v_amount, v_dest_offset, v_src_offset,

v_src_csid, v_lang_context, v_warning

);

- проверим v_warning на наличие неконвертируемых символов

IF (v_warning = DBMS_L0B.WARN_INCONVERTIBLE_CHAR) THEN

DBMS_OUTPUT.PUT_LINE('Warning! Inconvertible character.');

END IF;

- используем CL0SE() для закрытия v_src_bfile