F.17. dbms_lob — работа с большими объектами #
dbms_lob — это расширение Postgres Pro, позволяющее работать с большими объектами (LOB): BLOB, CLOB, BFILE и временными LOB. Расширение можно использовать для обращения к определённым частям больших объектов или большим объектам целиком и управления ими. Функциональность, предоставляемая этим модулем, во многом пересекается с функциональностью пакета DBMS_LOB в Oracle.
Примечание
Обратите внимание, что расширение dbms_lob зависит как от pgpro_bfile, так и от pgpro_sfile. Эти расширения необходимо установить до создания dbms_lob, либо можно установить все зависимости автоматически с помощью команды:
CREATE EXTENSION dbms_lob CASCADE;
F.17.1. Установка #
Расширение dbms_lob включено в состав Postgres Pro Enterprise как стандартное расширение. Чтобы задействовать dbms_lob, создайте расширение с помощью следующего запроса:
CREATE EXTENSION dbms_lob;
F.17.2. Типы данных #
Расширение dbms_lob работает с несколькими типами данных:
Тип
bfileпредоставляется расширением pgpro_bfile.CREATE TYPE BFILE AS ( dir_id int, file_name text );Таблица F.9. Параметры
bfileПараметр Описание dir_idИдентификатор каталога, в котором хранится bfile.file_nameИмя файла, из которого нужно прочитать bfile.Тип
blobхранит двоичные данные и имеет тот же интерфейс, что иBLOBв Oracle. Предоставляется расширением pgpro_sfile.CREATE TYPE dbms_lob.blob AS ( temp_data bytea, mime text, sf @extschema:pgpro_sfile@.sfile );Таблица F.10. Параметры
blobПараметр Описание sfОбъект типа sfileна диске, в котором хранятся объекты BLOB.temp_dataВременные данные BLOB, хранящиеся в памяти. mimeВспомогательные данные, которые определяют тип данных, хранящихся в BLOB. Тип
clobявляется эквивалентомCLOBиNCLOBв Oracle. Поддерживается только кодировка UTF-8.CREATE TYPE CLOB AS ( t text, istemp bool, mime text );Таблица F.11. Параметры
clobПараметр Описание tОбъект типа textна диске, в котором хранятся данные.istempОпределяет, является ли объект временным. mimeВспомогательные данные, которые определяют тип данных, хранящихся в CLOB.
F.17.3. Вспомогательные функции #
-
bfilename(#dirnametext,filenametext) returnsbfile Создаёт объект
bfile, связанный с физическим файлом в файловой системе. Здесьdirname— это имя объекта каталога, созданного функциейbfile_directory_create(), где находится файлfilename.-
empty_blob() returns#blob Создаёт пустой объект
blob, содержащий объект типаsfileбез данных. Его можно заполнить данными с помощью функций записи.-
empty_clob() returns#clob Создаёт пустой объект
clob, содержащий пустую строку. Его можно заполнить данными с помощью функций записи.-
to_blob(bbytea) returnsblob
to_blob(#fbfile,mime_typetext) returnsblob Преобразует объекты типа
byteaв объекты типаblob. Если исходным файлом являетсяbfile, можно указать тип данныхmime.-
to_clob(ttext) returnsclob
to_clob(tvarchar) returnsclob
to_clob(#bbfile,intcsid,mimetext) returnsclob Преобразует текстовые объекты в объекты типа
clob. Если исходным файлом являетсяbfile, его данные считываются и преобразуются в типclob. Поддерживается только кодировка UTF-8.-
to_raw(bblob) returnsclob
to_raw(#bbfile) returnsclob Копирует данные из файла типа
blobилиbfileв файл типаbytea. Обрабатывается только первый ГБ данных.
F.17.4. Функции и процедуры dbms_lob #
F.17.4.1. Открытие и закрытие больших объектов #
-
open(file_locIN OUTbfile,open_modeINint)
open(lob_locIN OUTblob,open_modeINint)
open(#lob_locIN OUTclob,open_modeINint) Открывает объект типа
bfile. Параметрopen_modeуказывает, в каком режиме будет открыт файл: чтения/записи или только для чтения. Для типаbfileподдерживается исключительно режим только для чтения (0). Функцииopen(иblob)open(не выполняют никаких действий и необходимы только для обеспечения совместимости синтаксиса.clob)-
isopen(file_locINbfile)
isopen(lob_locINblob)
isopen(#lob_locINclob) Проверяет, открыт ли объект типа
bfile. Возвращает 1, если LOB открыт, и 0 в противном случае. Функцииisopen(иblob)isopen(всегда возвращают 1 и необходимы только для обеспечения совместимости синтаксиса.clob)-
close(file_locIN OUTbfile)
close(lob_locIN OUTblob)
close(#lob_locIN OUTclob) Проверяет, открыт ли объект
bfile, и если да, то закрывает его. Функцииclose(иblob)close(не выполняют никаких действий и необходимы только для совместимости синтаксиса.clob)-
createtemporary(lob_locIN OUTblob,cacheINbool,durINintdefault 10)
createtemporary(#lob_locIN OUTclob,cacheINbool,durINintdefault 10) Создаёт временный объект LOB, в котором данные типа
blobхранятся как данные типаbytea, а данные типаclob— как данные типаtext.-
freetemporary(lob_locIN OUTblob)
freetemporary(#lob_locIN OUTclob) Освобождает ресурсы, связанные с временным большим объектом.
F.17.4.2. Чтение LOB #
-
getlength(file_locINbfile)
getlength(lob_locINblob)
getlength(#lob_locINclob) Возвращает длину
blobилиbfileв байтах илиclobв символах.-
read(file_locINbfile,amountIN OUTint,offsetINint,bufferOUTbytea)
read(lob_locINblob,amountIN OUTint,offsetINint,bufferOUTbytea)
read(#lob_locINclob,amountIN OUTint,offsetINint,bufferOUTtext) Считывает часть LOB и записывает указанное количество байтов (для
blob/bfile) или символов (дляclob) в буфер (buffer), начиная с абсолютного смещения (offset) от начала LOB. Обратите внимание, что для чтения с начала файла необходимо указать для параметраoffsetзначение 1.-
get_storage_limit(lob_locINblob)
get_storage_limit(#lob_locINclob) Возвращает размер хранилища LOB для указанного LOB.
-
substr(file_locINbfile,amountINint,offsetINint)
substr(lob_locINblob,amountINint,offsetINint)
substr(#lob_locINclob,amountINint,offsetINint) Возвращает количество (
amount) байтов (дляblob/bfile) или символов (дляclob) LOB, начиная с абсолютного смещения (offset) от начала LOB.-
instr(file_locINbfile,patternINint,offsetINbigintdefault 1,nthINbigintdefault 1)
instr(lob_locINblob,patternINint,offsetINbigintdefault 1,nthINbigintdefault 1)
instr(#lob_locINclob,patternINint,offsetINbigintdefault 1,nthINbigintdefault 1) Возвращает соответствующую позицию n-ого (
nth) вхождения шаблона (pattern) в LOB, начиная с указанного смещения (offset). Возвращает 0, если шаблонpatternне найден. Поиск осуществляется только в первом ГБ данных.
F.17.4.3. Изменение LOB #
-
write(lob_locIN OUTblob,amountINint,offsetINbigint,bufferINbytea)
write(#lob_locIN OUTclob,amountINint,offsetINint,bufferINtext) Записывает заданный объём данных (
amount) во внутренний LOB, начиная с абсолютного смещения (offset) от начала LOB. Данные берутся из параметраbuffer. Если указанное значениеoffsetпревышает текущий размер LOB, значение дополняется нулевыми байтами дляblobили пробелами дляclob.Если
bufferдлиннее, чемamount, записывается только указанное количество байт (дляblob) или символов (дляclob). Это гарантирует, что во внутренний LOB будет записано ровноamountданных.-
writeappend(lob_locIN OUTblob,amountINint,bufferINbytea)
writeappend(#lob_locIN OUTclob,amountINint,bufferINtext) Записывает указанный объём (
amount) данных в конец внутреннего LOB. Данные записываются из буфера, указанного в параметреbuffer.-
erase(lob_locIN OUTblob,amountIN OUTint,offsetINbigintdefault 1)
erase(#lob_locIN OUTclob,amountIN OUTint,offsetINintdefault 1) Удаляет весь внутренний LOB или часть внутреннего LOB. Когда данные стираются из середины LOB, записываются нулевые байтовые заполнители (для временных
blob) или пробелы (дляclob). Постоянные объекты типаblobмогут быть удалены только целиком.-
trim(lob_locIN OUTblob,newlenINbigint)
trim(#lob_locIN OUTclob,newlenINint) Обрезает значение внутреннего LOB до длины, указанной в параметре
newlen. Необходимо указать длину в байтах для временногоblobи длину в символах дляclob. Применимо для постоянногоblob, только если новая длина равна нулю, что означает удаление объекта.
F.17.4.4. Операции с несколькими LOB #
-
compare(lob_1INbfile,lob_2INbfile,amountINbigint,offset_1INbigintdefault 1,offset_2INbigintdefault 1) returns int
compare(lob_1INblob,lob_2INblob,amountINintdefault 1024*1024*1024-8,offset_1INbigintdefault 1,offset_2INbigintdefault 1) returns int
compare(#lob_1INclob,lob_2INclob,amountINintdefault (1024*1024*1024-8)/2,offset_1INintdefault 1,offset_2INintdefault 1) returns int Сравнивает два полных LOB или части двух LOB. Можно сравнивать только LOB, имеющие одинаковые типы данных. Для
bfileиblobвыполняется двоичное сравнение. Дляclobфайлы сравниваются в соответствии с текущим правилом сортировки базы данных.-
append(lob_1IN OUTblob,lob_2INblob)
append(#lob_1IN OUTclob,lob_2INclob) Добавляет содержимое исходного внутреннего LOB в целевой LOB. Исходный LOB добавляется полностью.
-
copy(dest_lobIN OUTblob,src_lobINblob,amountINbigint,dest_offsetINbigintdefault 1,src_offsetINbigintdefault 1) returnsint
copy(#dest_lobIN OUTclob,src_lobINclob,amountINint,dest_offsetINintdefault 1,src_offsetINintdefault 1) returnsint Копирует весь или часть исходного внутреннего LOB в целевой внутренний LOB. Можно указать смещение как для исходного, так и для целевого LOB, а также количество байтов или символов для копирования.
-
converttoblob(#dest_lobIN OUTblob,src_clobINclob,amountINint,dest_offsetIN OUTbigint,src_offsetIN OUTint,blob_csidINint,lang_contextIN OUTint,warningOUTint) Считывает символьные данные из исходного
clob, преобразует эти данные в указанный набор символов, записывает преобразованные данные в целевойblobв двоичном формате и возвращает новые смещения. Поддерживается только кодировка UTF-8.-
converttoclob(#dest_lobIN OUTclob,src_blobINblob,amountINint,dest_offsetIN OUTint,src_offsetIN OUTbigint,blob_csidINint,lang_contextIN OUTint,warningOUTint) Считывает двоичные данные из исходного
blob, преобразует их в кодировку UTF-8 и записывает преобразованные символьные данные в целевойclob.
F.17.4.5. Устаревшие API #
-
fileexists(#file_locINbfile) returnsint Проверяет, действительно ли существует в файловой системе файл, на который указывает заданный указатель
bfile. Реализовано какbfile_fileexists.-
fileopen(#file_locIN OUTbfile,open_modeINint) returnsint Открывает указанный
bfileв режиме только для чтения. Реализовано как функцияbfile_open.-
fileisopen(#file_locINbfile) returnsint Проверяет, открыт ли указанный
bfile.-
loadfromfile(#dest_lobIN OUTblob,src_bfileINbfile,amountINintdefault 1024*1024*1024-8,dest_offsetINbigintdefault 1,src_offsetINbigintdefault 1) Преобразует данные из указанного
bfileвblob.-
fileclose(#file_locIN OUTbfile) Закрывает ранее открытый
bfile. Реализовано как функцияbfile_close.-
filecloseall()# Закрывает все файлы
bfile, открытые в сеансе. Реализовано какbfile_close_all.-
filegetname(#file_locINbfile,dir_aliasOUTtext,filenameOUTtext) Определяет объект каталога и имя файла. Эта функция показывает только имя объекта каталога и имя файла, назначенные указателю, а не подтверждает факт существования физического файла или каталога. Реализовано как функция
bfile_directory_get_alias_by_id.
F.17.4.6. Прочие параметры #
-
loadblobfromfile(#dest_lobIN OUTblob,src_bfileINbfile,amountINintdefault 1024*1024*1024-8,dest_offsetINbigintdefault 1,src_offsetINbigintdefault 1) returnsint Синоним для
loadfromfile().-
loadclobfromfile(#dest_lobIN OUTclob,src_bfileINbfile,amountINint,dest_offsetIN OUTint,src_offsetIN OUTbigint,bfile_csidINint,lang_contextIN OUTint,warningOUTint) Загружает данные из
bfileво внутреннийclob.-
setcontenttype(lob_locIN OUTblob,contenttypeINtext)
setcontenttype(#lob_locIN OUTclob,contenttypeINtext) Устанавливает строку типа содержимого, связанную с LOB.
-
getcontenttype(lob_locINblob) returnstext
getcontenttype(#lob_locINclob) returnstext Возвращает строку типа содержимого, связанную с LOB.
-
getchunksize(lob_locINblob) returnstext
getchunksize(#lob_locINclob) returnstext Возвращает объём пространства, используемого в порции LOB для хранения значения LOB.
F.17.5. Пример #
Ниже приведён пример работы расширения dbms_lob.
DO $$ DECLARE cur_clob dbms_lob.clob; buffer text; amount int := 3000; BEGIN cur_clob := dbms_lob.empty_clob(); cur_clob.t := 'just some sample text'; raise notice 'clob length: %', dbms_lob.getlength(cur_clob); call dbms_lob.read(cur_clob, amount, 1, buffer); raise notice 'all clob read: %', buffer; amount := 6; call dbms_lob.read(cur_clob, amount, 4, buffer); raise notice 'clob read from 4 position for 6 symbols: %', buffer; raise notice 'storage limit: %', dbms_lob.get_storage_limit(cur_clob); raise notice 'clob substr from 6 position for 8 symbols: %', dbms_lob.substr(cur_clob, 8, 6); raise notice 'third postion of letter s in clob: %', dbms_lob.instr(cur_clob, 's', 1, 3); call dbms_lob.write(cur_clob, 6, 4, 'foobar'); raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.write(cur_clob, 3, 25, 'baz'); raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.writeappend(cur_clob, 4, 'test'); raise notice 'new clob contents: %', cur_clob.t; amount := 3; call dbms_lob.erase(cur_clob, amount, 2); raise notice 'amount of symbols deleted: %', amount; raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.erase(cur_clob, amount, 30); raise notice 'amount of symbols deleted: %', amount; raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.trim_(cur_clob, 22); raise notice 'new clob contents: %', cur_clob.t; END; $$; --output NOTICE: clob length: 21 NOTICE: all clob read: just some sample text NOTICE: clob read from 4 position for 6 symbols: t some NOTICE: storage limit: 536870908 NOTICE: clob substr from 6 position for 8 symbols: some sam NOTICE: third postion of letter s in clob: 11 NOTICE: new clob contents: jusfoobar sample text NOTICE: new clob contents: jusfoobar sample text baz NOTICE: new clob contents: jusfoobar sample text baztest NOTICE: amount of symbols deleted: 3 NOTICE: new clob contents: j oobar sample text baztest NOTICE: amount of symbols deleted: 2 NOTICE: new clob contents: j oobar sample text bazte NOTICE: new clob contents: j oobar sample text
А вот так может выглядеть работа с LOB, находящимися в базе данных:
-- Создание таблицы и добавление данных
CREATE TABLE dbms_lob_test (id INTEGER GENERATED ALWAYS AS IDENTITY, blob_col DBMS_LOB.BLOB);
INSERT INTO dbms_lob_test (blob_col) VALUES (dbms_lob.to_blob(decode('d6b7a686ab4d4e9c5d2cbf49db6bc0f1', 'hex')));
DO $$
DECLARE
v_lob_loc DBMS_LOB.BLOB;
v_buffer BYTEA;
v_amount INTEGER := 32700;
v_offset BIGINT := 1;
v_length BIGINT;
BEGIN
SELECT (blob_col).* INTO v_lob_loc FROM dbms_lob_test WHERE id=1;
CALL dbms_lob.open(v_lob_loc, 0); -- Для DBMS_LOB.BLOB не обязательно
SELECT DBMS_LOB.getlength(v_lob_loc) into v_length;
RAISE NOTICE 'BLOB len=%', v_length;
CALL dbms_lob.read(v_lob_loc, v_amount, v_offset, v_buffer);
RAISE NOTICE 'Read % bytes', v_amount;
RAISE NOTICE 'Buffer: %', encode(v_buffer, 'hex');
CALL dbms_lob.close(v_lob_loc); -- Для DBMS_LOB.BLOB не обязательно
END $$;Вывод будет выглядеть вот так:
BLOB len=16 Read 16 bytes Buffer: d6b7a686ab4d4e9c5d2cbf49db6bc0f1