sql >> Databasteknik >  >> RDS >> Oracle

ORA-22275:ogiltig LOB-locator specificerad

Ja. En LOB är en pekare/referens till ett minne/diskminne. Du måste "memalloc()" (...initiera) lagringen först, tilldela pekaren/referensen till din LOB-variabel. Det är vad dbms_lob.createTemporary() är för. Om du inte initierar en LOB-variabel med en giltig LOB-lokaliserare, kommer alla dina operationer på den LOB-variabeln att misslyckas med ORA-22275: invalid LOB locator specified .

Förbättring: Få din PL/SQL-funktion omstrukturerad lite:(Och observera att jag använde en dummy-fråga för last_60_cpu_cursor markören. Återanvänd inte markören, använd din egen! :-))

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. Du behöver inte öppna+hämta+stänga markören. En vanlig markörslinga kommer att fungera bra (om inte ännu bättre, tack vare den implicita bulkhämtningen under huvarna).
  2. Deklarera uttryckligen den tillfälliga LOB som cachad (cache => true; som du redan har). Detta säkerställer att databitar läggs till i LOB i minnet, istället för att läggas till på disken (cache => false ).
  3. Sätt ihop strängarna som ska läggas till LOB för att minimera antalet anrop till dbms_lob.append() .
  4. Ta bort dbms_output.put_line() från din funktion. I händelse av LOB-innehåll större än 32K, skulle detta skapa ett undantag ändå.

När du är klar med att leverera LOB tillbaka till din Java-env., frigör den tillfälliga LOB . (Jag är inte en Java-kille, kan inte skriva Java-kodavsnittet själv.)

Du har också ett konceptuellt fel i din Java-kod; registrerar returen av funktionen som Types.VARCHAR är fel. Du bör hellre använda Oracles dedikerade CLOB-typ . (Jag har sett de i C#, Java måste också ha dem.)

Det finns också ett prestandaproblem med din lösning. Din funktion returnerar en LOB. I PL/SQL returneras varje funktionsvärde till sin anropare som en djup kopia av det inre värdet. Därför, om du returnerar en LOB från en funktion dupliceras LOB-innehållet i bakgrunden med en ny LOB-locator(/pekare/referens). Du bör använda Du kan överväga att använda en lagrad procedur istället för en funktion och skicka LOB till Java som en out nocopy parameter. Den lagrade processen skulle då se ut så här:

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;

Hur ditt Java-samtal skulle se ut är upp till dig och JDBC-dokument ; men, förvisso, en LOB som returneras på detta sätt skulle innebära ingen kopiering av bakgrundsinnehåll. Naturligtvis gäller fortfarande behovet av att frigöra den tilldelade tillfälliga LOB.



  1. Kontrollera om det finns ett värde i Postgres-arrayen

  2. En affärsdatamodell för prenumeration

  3. Vad står TX- och XID-fraktioner för i postgres pgadmin-verktyget

  4. hur man använder dbms_scheduler för att köra jobbet var 30:e minut