sql >> Databáze >  >> RDS >> Oracle

ORA-22275:zadán neplatný lokátor LOB

Ano. LOB je ukazatel/odkaz na paměť/disk úložiště. Nejprve musíte "memalloc()" (... inicializovat) úložiště, přiřadit ukazatel/odkaz vaší proměnné LOB. To je to, co dbms_lob.createTemporary() je pro. Pokud neinicializujete proměnnou LOB s platným lokátorem LOB, všechny vaše operace s touto proměnnou LOB selžou s ORA-22275: invalid LOB locator specified .

Vylepšení: Nechte svou funkci PL/SQL trochu refaktorovat:(A prosím, všimněte si, že jsem použil fiktivní dotaz pro last_60_cpu_cursor kurzor. Nepoužívejte kurzor znovu, použijte svůj vlastní! :-))

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. Není třeba otevírat+načítat+zavírat kurzor. Běžná kurzorová smyčka bude fungovat dobře (ne-li ještě lépe, díky implicitnímu hromadnému načítání pod kryty).
  2. Explicitně deklarujte dočasný objekt LOB jako uložený v mezipaměti (cache => true; jak už máte). To zajišťuje, že se datové bloky přidávají do LOB v paměti, místo aby byly přidávány na disk (cache => false ).
  3. Zřetězte řetězce, které mají být připojeny k LOB, aby se minimalizoval počet volání dbms_lob.append() .
  4. Odstraňte dbms_output.put_line() z vaší funkce. V případě obsahu LOB většího než 32 kB by to stejně vyvolalo výjimku.

Poté, co skončíte s doručením LOB zpět do vašeho prostředí Java, uvolněte dočasný LOB . (Nejsem Java chlap, neumím napsat úryvek kódu Java sám.)

Také máte koncepční chybu v kódu Java; registrace návratu funkce jako Types.VARCHAR je špatně. Raději byste měli použít vyhrazený typ CLOB společnosti Oracle . (Viděl jsem je v C#, Java je musí mít také.)

Vaše řešení má také jeden problém s výkonem. Vaše funkce vrací LOB. V PL/SQL je každá hodnota funkce vrácena svému volajícímu jako hluboká kopie vnitřní hodnoty. Pokud tedy vrátíte LOB z funkce, obsah LOB je duplikován na pozadí s novým lokátorem LOB (/ukazatel/odkaz). Měli byste použít Můžete zvážit použití uložené procedury místo funkce a předat LOB do Javy jako out nocopy parametr. Uložený proces by pak vypadal takto:

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;

Jak bude vaše volání Java vypadat, je na vás a Dokument JDBC ; ale zajisté by LOB vrácený tímto způsobem neznamenal žádné kopírování obsahu na pozadí. Samozřejmě stále platí potřeba uvolnit přidělený dočasný LOB.



  1. Jak používat Case Statement pro podmíněné formátování ve Select Query - SQL Server / TSQL výukový program, část 116

  2. MariaDB ROWNUM() Vysvětleno

  3. Vynutit Oracle Drop Global Temp Table

  4. Zobrazit ID číslo v URL a načíst výsledky databáze z ID čísla do textových polí