Ano. LOB je ukazatel/odkaz na paměť/disk úložiště. Nejprve musíte "memalloc()" (... inicializovat) úložiště, přiřadit ukazatel/odkaz vaší proměnné LOB. To je to, co dbms_lob.createTemporary()
je pro. Pokud neinicializujete proměnnou LOB s platným lokátorem LOB, všechny vaše operace s touto proměnnou LOB selžou s ORA-22275: invalid LOB locator specified
.
Vylepšení: Nechte svou funkci PL/SQL trochu refaktorovat:(A prosím, všimněte si, že jsem použil fiktivní dotaz pro last_60_cpu_cursor
kurzor. Nepoužívejte kurzor znovu, použijte svůj vlastní! :-))
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;
- Není třeba otevírat+načítat+zavírat kurzor. Běžná kurzorová smyčka bude fungovat dobře (ne-li ještě lépe, díky implicitnímu hromadnému načítání pod kryty).
- Explicitně deklarujte dočasný objekt LOB jako uložený v mezipaměti (
cache => true
; jak už máte). To zajišťuje, že se datové bloky přidávají do LOB v paměti, místo aby byly přidávány na disk (cache => false
). - Zřetězte řetězce, které mají být připojeny k LOB, aby se minimalizoval počet volání
dbms_lob.append()
. - Odstraňte
dbms_output.put_line()
z vaší funkce. V případě obsahu LOB většího než 32 kB by to stejně vyvolalo výjimku.
Poté, co skončíte s doručením LOB zpět do vašeho prostředí Java, uvolněte dočasný LOB . (Nejsem Java chlap, neumím napsat úryvek kódu Java sám.)
Také máte koncepční chybu v kódu Java; registrace návratu funkce jako Types.VARCHAR
je špatně. Raději byste měli použít vyhrazený typ CLOB společnosti Oracle
. (Viděl jsem je v C#, Java je musí mít také.)
Vaše řešení má také jeden problém s výkonem. Vaše funkce vrací LOB. V PL/SQL je každá hodnota funkce vrácena svému volajícímu jako hluboká kopie vnitřní hodnoty. Pokud tedy vrátíte LOB z funkce, obsah LOB je duplikován na pozadí s novým lokátorem LOB (/ukazatel/odkaz). Měli byste použít Můžete zvážit použití uložené procedury místo funkce a předat LOB do Javy jako out nocopy
parametr. Uložený proces by pak vypadal takto:
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;
Jak bude vaše volání Java vypadat, je na vás a Dokument JDBC ; ale zajisté by LOB vrácený tímto způsobem neznamenal žádné kopírování obsahu na pozadí. Samozřejmě stále platí potřeba uvolnit přidělený dočasný LOB.