Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

ORA-22275:localizador LOB inválido especificado


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;
  1. 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).
  2. 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 ).
  3. Concatene as strings a serem anexadas ao LOB para minimizar o número de chamadas para o dbms_lob.append() .
  4. 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.)

Além disso, há um problema de desempenho com sua solução. Sua função retorna um LOB. Em PL/SQL, cada valor de função é retornado ao seu chamador como uma cópia profunda do valor interno. Portanto, se você retornar um LOB de uma função, o conteúdo do LOB será duplicado em segundo plano com um novo localizador de LOB (/pointer/reference). Você deve usar Você pode considerar usar um procedimento armazenado em vez de uma função e passar o LOB para Java como um 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.