sql >> Database >  >> RDS >> Oracle

ORA-22275:ongeldige LOB-locator opgegeven

Ja. Een LOB is een aanwijzer/verwijzing naar een geheugen/schijfopslag. U moet eerst de opslag "memalloc()" (... initialiseren) en de aanwijzer/referentie toewijzen aan uw LOB-variabele. Dat is wat dbms_lob.createTemporary() is voor. Tenzij u een LOB-variabele initialiseert met een geldige LOB-locator, mislukken al uw bewerkingen op die LOB-variabele met ORA-22275: invalid LOB locator specified .

Verbetering: Laat je PL/SQL-functie een beetje refactoren:(En houd er rekening mee dat ik een dummy-query heb gebruikt voor de last_60_cpu_cursor cursor. Gebruik de cursor niet opnieuw, maar gebruik die van uzelf! :-))

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. Je hoeft de cursor niet te openen+ophalen+sluiten. Een gewone cursor-loop doet het prima (zo niet zelfs beter, dankzij de impliciete bulk-fetching onder de motorkappen).
  2. Verklaar de tijdelijke LOB expliciet als gecached (cache => true; zoals je al hebt). Dit zorgt ervoor dat gegevensblokken worden toegevoegd aan de LOB in het geheugen, in plaats van dat ze op schijf worden toegevoegd (cache => false ).
  3. Voeg de tekenreeksen samen die aan de LOB moeten worden toegevoegd om het aantal aanroepen naar de dbms_lob.append() te minimaliseren .
  4. Verwijder de dbms_output.put_line() vanuit je functie. In het geval van LOB-inhoud groter dan 32K, zou dit sowieso een uitzondering veroorzaken.

Nadat u klaar bent met het terugbrengen van de LOB naar uw Java-omgeving, de tijdelijke LOB vrijmaken . (Ik ben geen Java-man, kan het Java-codefragment zelf niet schrijven.)

Ook heb je een conceptuele fout in je Java-code; het registreren van de terugkeer van de functie als Types.VARCHAR is fout. Gebruik liever het het speciale CLOB-type van Oracle . (Ik heb die in C# gezien, Java moet ze ook hebben.)

Er is ook een prestatieprobleem met uw oplossing. Uw functie retourneert een LOB. In PL/SQL wordt elke functiewaarde teruggestuurd naar de aanroeper als een diepe kopie van de interne waarde. Als u dus een LOB van een functie retourneert, wordt de LOB-inhoud op de achtergrond gedupliceerd met een nieuwe LOB-locator (/pointer/reference). Je zou moeten gebruiken U kunt overwegen om een ​​opgeslagen procedure te gebruiken in plaats van een functie en de LOB door te geven aan Java als een out nocopy parameter. Het opgeslagen proces ziet er dan als volgt uit:

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;

Hoe uw Java-oproep eruitziet, is aan u en JDBC-document ; maar een LOB die op deze manier wordt geretourneerd, zou zeker betekenen dat er geen achtergrondinhoud wordt gekopieerd. Natuurlijk blijft de noodzaak om de toegewezen tijdelijke LOB vrij te maken nog steeds van kracht.



  1. SQL Server:verschil tussen PARTITION BY en GROUP BY

  2. Sql:Optimalisatie BETWEEN-clausule

  3. Hoe converteer ik een geheel getal (tijd) naar HH:MM:SS::00 in SQL Server 2008?

  4. Automatisch teruggestuurde e-mailadressen uit de database verwijderen?