Sim. Um LOB é um ponteiro/referência para um armazenamento de memória/disco. Você precisa "memalloc()" (... inicializar) o armazenamento primeiro, atribuir o ponteiro/referência à sua variável LOB. É isso que
dbms_lob.createTemporary()
é para. A menos que você inicialize uma variável LOB com um localizador LOB válido, todas as suas operações nessa variável LOB falharão com ORA-22275: invalid LOB locator specified
. Aprimoramento: Refatore um pouco sua função PL/SQL:(E observe que usei uma consulta fictícia para o
last_60_cpu_cursor
cursor. Não reutilize o cursor, use o seu próprio! :-)) 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;
- Você não precisa abrir+buscar+fechar o cursor. Um loop de cursor regular funcionará bem (se não for ainda melhor, graças à busca em massa implícita nos bastidores).
- Declarar explicitamente o LOB temporário como armazenado em cache (
cache => true
; como você já tem). Isso garante que os pedaços de dados sejam adicionados ao LOB na memória, em vez de serem adicionados no disco (cache => false
). - Concatene as strings a serem anexadas ao LOB para minimizar o número de chamadas para o
dbms_lob.append()
. - Remova o
dbms_output.put_line()
da sua função. No caso de conteúdo LOB maior que 32 K, isso geraria uma exceção de qualquer maneira.
Além disso, depois de entregar o LOB de volta ao seu ambiente Java, livre o LOB temporário . (Eu não sou um cara de Java, não posso escrever o trecho de código Java sozinho.)
Além disso, você tem um erro conceitual em seu código Java; registrando o retorno da função como
Types.VARCHAR
está errado. Você deve usar o tipo CLOB dedicado do Oracle
. (Eu vi aqueles em C#, Java deve tê-los também.) out nocopy
parâmetro. O proc armazenado ficaria assim: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;
Como seria sua chamada Java, depende de você e Documento JDBC ; mas, com certeza, um LOB retornado dessa maneira significaria nenhuma cópia de conteúdo em segundo plano. Obviamente, a necessidade de liberar o LOB temporário alocado ainda se aplica.