) 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