sql >> Database teknologi >  >> RDS >> Oracle

ORA-22275:ugyldig LOB-locator angivet

Ja. En LOB er en pointer/reference til en hukommelse/disklager. Du skal først "memalloc()" (... initialisere) lageret, tildele markøren/referencen til din LOB-variabel. Det er hvad dbms_lob.createTemporary() er for. Medmindre du initialiserer en LOB-variabel med en gyldig LOB-locator, vil alle dine operationer på den LOB-variabel mislykkes med ORA-22275: invalid LOB locator specified .

Forbedring: Få din PL/SQL-funktion omdannet lidt:(Og bemærk venligst, at jeg brugte en dummy-forespørgsel til last_60_cpu_cursor cursoren. Genbrug ikke markøren, brug 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 ikke at åbne+hent+lukke markøren. En almindelig markørsløjfe vil klare sig fint (hvis ikke endnu bedre, takket være den implicitte bulk-hentning under hætterne).
  2. Erklærer eksplicit den midlertidige LOB som cachelagret (cache => true; som du allerede har). Dette sikrer, at datastykker tilføjes til LOB i hukommelsen i stedet for at blive tilføjet på disken (cache => false ).
  3. Sæt de strenge, der skal tilføjes til LOB'en, for at minimere antallet af kald til dbms_lob.append() .
  4. Fjern dbms_output.put_line() fra din funktion. I tilfælde af LOB-indhold større end 32K, ville dette alligevel give en undtagelse.

Når du er færdig med at levere LOB tilbage til din Java-env., frigør den midlertidige LOB . (Jeg er ikke en Java-fyr, kan ikke selv skrive Java-kodestykket.)

Du har også en begrebsfejl i din Java-kode; registrering af returneringen af ​​funktionen som Types.VARCHAR er forkert. Du bør hellere bruge Oracles dedikerede CLOB-type . (Jeg har set dem i C#, dem skal Java også have.)

Der er også et ydelsesproblem med din løsning. Din funktion returnerer en LOB. I PL/SQL returneres hver funktionsværdi til dens kaldere som en dyb kopi af den indvendige værdi. Derfor, hvis du returnerer en LOB fra en funktion, duplikeres LOB-indholdet i baggrunden med en ny LOB-locator(/pointer/reference). Du bør bruge Du kan overveje at bruge en lagret procedure i stedet for en funktion og videregive LOB til Java som en out nocopy parameter. Den lagrede proc ville så se sådan ud:

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;

Hvordan vil dit Java-opkald se ud, er op til dig og JDBC-dokument ; men en LOB returneret på denne måde ville helt sikkert betyde ingen kopiering af baggrundsindhold. Behovet for at frigøre den tildelte midlertidige LOB gælder naturligvis stadig.



  1. hvorfor denne sql brugte union alle returnerede ingen data

  2. mysql kommandolinje returudførelsestid?

  3. Kan en indsættelsesoperation få en anden DDL-operation til at vente?

  4. Weblogic Deployment Exception:PaddingException:Kunne ikke udføre unpadding:ugyldig pad-byte