да LOB е указател/препратка към памет/диск за съхранение. Първо трябва да "memalloc()" (... инициализирате) хранилището, да присвоите указателя/препратката към вашата LOB променлива. Това е, което dbms_lob.createTemporary()
е за. Освен ако не инициализирате LOB променлива с валиден LOB локатор, всички ваши операции върху тази LOB променлива ще се провалят с ORA-22275: invalid LOB locator specified
.
Подобрение: Преработете малко вашата PL/SQL функция:(И моля, обърнете внимание, че използвах фиктивна заявка за last_60_cpu_cursor
курсор. Не използвайте повторно курсора, използвайте свой собствен! :-))
create or replace
function statistics_function
( namein in varchar2 )
return clob
is
line clob;
cursor last_60_cpu_cursor is
select 1 as last_60_cpu, sysdate as last_60_event_date
from dual
;
begin
dbms_lob.createtemporary(lob_loc => line, cache => true, dur => dbms_lob.call);
for cv in last_60_cpu_cursor loop
dbms_lob.append(line, to_char(cv.last_60_event_date)||'i'||to_char(cv.last_60_cpu)||chr(10));
end loop;
dbms_lob.append(line, 'last_60_cpu'||chr(10));
return line;
end statistics_function;
- Не е необходимо да отваряте+извличате+затваряте курсора. Обикновен цикъл на курсора ще се справи добре (ако не и по-добре, благодарение на имплицитното групово извличане под капаците).
- Изрично декларирайте временния LOB като кеширан (
cache => true
; както вече имате). Това гарантира, че частите от данни се добавят към LOB в паметта, вместо да се добавят на диска (cache => false
). - Свържете низовете, които ще бъдат добавени към LOB, така че да минимизирате броя на извикванията към
dbms_lob.append()
. - Премахнете
dbms_output.put_line()
от вашата функция. В случай на LOB съдържание, по-голямо от 32K, това така или иначе ще предизвика изключение.
Освен това, след като приключите с доставянето на LOB обратно във вашата Java среда, освободете временния LOB . (Не съм Java човек, не мога сам да напиша кодовия фрагмент на Java.)
Освен това имате концептуална грешка във вашия Java код; регистриране на връщането на функцията като Types.VARCHAR
не е наред. По-скоро трябва да използвате специалния CLOB тип на Oracle
. (Виждал съм ги в C#, Java също трябва да ги има.)
Освен това има един проблем с производителността на вашето решение. Вашата функция връща LOB. В PL/SQL всяка стойност на функцията се връща на извикващия я като дълбоко копие на вътрешната стойност. Следователно, ако върнете LOB от функция, LOB съдържанието се дублира във фонов режим с нов LOB локатор (/указател/референция). Трябва да използвате Може да обмислите използването на съхранена процедура вместо функция и да предадете LOB на Java като out nocopy
параметър. Тогава съхранената процедура ще изглежда така:
create or replace
procedure statistics_function
( namein in varchar2
, lob_out out nocopy clob )
is
cursor last_60_cpu_cursor is
select 1 as last_60_cpu, sysdate as last_60_event_date
from dual
;
begin
dbms_lob.createtemporary(lob_loc => lob_out, cache => true, dur => dbms_lob.session);
for cv in last_60_cpu_cursor loop
dbms_lob.append(lob_out, to_char(cv.last_60_event_date)||'i'||to_char(cv.last_60_cpu)||chr(10));
end loop;
dbms_lob.append(lob_out, 'last_60_cpu'||chr(10)||chr(10));
end statistics_function;
Как ще изглежда вашето Java обаждане, зависи от вас и JDBC документ ; но със сигурност LOB, върнат по този начин, би означавал липса на копиране на фоново съдържание. Разбира се, необходимостта от освобождаване на разпределения временен LOB все още е в сила.