Вставить тестовую строку BLOB размером более 2000 или 4000 байт
у меня есть таблица в Oracle с BLOB
столбец, который может хранить XMLs, а также XMLs
на молнии. Это требования заказчика, и их нельзя изменить. Таблицы будут созданы, и я должен прочитать и работать с некоторой информацией внутри BLOBs
.
Я исследовал, и любое из неясных решений было ясно или работало для меня.
проблема, с которой я сталкиваюсь, заключается в том, что INSERT
XML
простые данные больше, чем 2000 bytes
С utl_raw.cast_to_raw
используя DBeaver
как менеджер баз данных. Я получил сообщение:
SQL Error [6502] [65000]: ORA-06502: PL/SQL: numeric or value error: raw variable length too long ORA-06512: at "SYS.UTL_RAW", line 224
java.sql.SQLException: ORA-06502: PL/SQL: numeric or value error: raw variable length too long
ORA-06512: at "SYS.UTL_RAW", line 224
проблемы
- я исследовал и
UTL_RAW
не может превышать2000 bytes
- кажется, что есть еще одно ограничение
4000 bytes
наBLOBs
в Oracle
что я мог сделать для этих дел?
2 ответов
для начала вам нужно понять, что такое поле. Они являются "большими данными", возможно, больше, чем любые другие типы данных в Oracle. Они похожи на обычные файлы в файловой системе. Для того, чтобы записать в файл на filesytem, вам придется
- открыть файл для записи
- усечь файл, если вы хотите начать заполнять его с нуля
- прочитайте ваши исходные данные в кусках в цикле
- добавьте фрагменты данных в файл в такую же петлю, по одному
- закрыть файл
более или менее то же самое верно для LOBs. В вашей таблице столбец LOB (CLOB/BLOB/NCLOB) - это просто указатель/ссылка на другое место на вашем диске, содержащее фактические данные. В стандартных терминах Oracle указатель называется "LOB locator". Вам нужно
- открыть/инициализировать локатор LOB
- усечь содержимое LOB, если вы хотите начать заполнять его с скретч!--14-->
- добавьте куски данных в содержимое LOB в цикле, один за другим
- закройте локатор LOB
в PL/SQL это может выглядеть так:
-- create table blob_test(id number, b blob);
declare
v_b blob;
aaa raw(32767);
longLine varchar2(32767);
begin
longLine := LPAD('aaaa', 32767,'x');
aaa := UTL_RAW.CAST_TO_RAW(longLine);
insert into blob_test values(1,empty_blob()) returning b into v_b;
dbms_lob.open(v_b,dbms_lob.lob_readwrite);
dbms_lob.writeappend(v_b,UTL_RAW.LENGTH (aaa) ,aaa);
dbms_lob.close(LOB_LOC=>v_b);
commit;
end;
объяснение:
- инициализировать локатор LOB =
insert into blob_test values(1,empty_blob()) returning b into v_b;
- откройте локатор LOB для записи =
dbms_lob.open(v_b,dbms_lob.lob_readwrite);
- усечь содержимое LOB, если вы хотите начать заполнять его с нуля ... Это делается
empty_blob()
звоните вinsert
. - добавьте куски данных в содержимое LOB в цикле, один за другим = здесь только одна итерация
dbms_lob.writeappend()
, добавляя только один кусокaaa
длинойutl_raw.length(aaa)
(максимум 32767) в лобv_b
- закройте локатор LOB =
dbms_lob.close(LOB_LOC=>v_b);
функции utl_raw.cast_to_raw
преобразует значение типа данных VARCHAR2 в необработанное значение. Очевидно, что длина строки ограничена типом данных VARCHAR2. Если вам нужно конвертировать большие текстовые данные в LOB вы можете использовать DBMS_LOB.CONVERTTOBLOB процедуры.
например, вы можете создать функцию для преобразования большого строкового значения (clob в качестве входного) в blob. что-то вроде этого ...--5-->
create or replace function ClobToBlob (p_clob in clob) return blob is
l_dest_offset integer := 1;
l_source_offset integer := 1;
p_csid number := 0;
l_lang_context integer := DBMS_LOB.DEFAULT_LANG_CTX;
l_warning integer := DBMS_LOB.WARN_INCONVERTIBLE_CHAR;
l_tmpblob blob;
begin
dbms_lob.createtemporary(l_tmpblob, true);
DBMS_LOB.CONVERTTOBLOB
(
l_tmpblob,
p_clob,
DBMS_LOB.LOBMAXSIZE,
l_dest_offset,
l_source_offset,
p_csid,
l_lang_context,
l_warning
);
return l_tmpblob;
end;