Ya. LOB adalah penunjuk/referensi ke memori/penyimpanan disk. Anda perlu "memalloc()" (... menginisialisasi) penyimpanan terlebih dahulu, menetapkan pointer/referensi ke variabel LOB Anda. Itulah dbms_lob.createTemporary()
adalah untuk. Kecuali Anda menginisialisasi variabel LOB dengan pencari LOB yang valid, semua operasi Anda pada variabel LOB itu akan gagal dengan ORA-22275: invalid LOB locator specified
.
Peningkatan: Apakah fungsi PL/SQL Anda di-refactored sedikit:(Dan harap dicatat bahwa saya menggunakan kueri dummy untuk last_60_cpu_cursor
kursor. Jangan gunakan kembali kursor, gunakan milik Anda sendiri! :-))
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;
- Anda tidak perlu membuka+mengambil+menutup kursor. Kursor-loop biasa akan baik-baik saja (jika tidak lebih baik, berkat pengambilan massal implisit di bawah tenda).
- Deklarasikan LOB sementara secara eksplisit sebagai cache (
cache => true
; seperti yang sudah Anda miliki). Ini memastikan potongan data ditambahkan ke LOB di memori, alih-alih ditambahkan pada disk (cache => false
). - Menggabungkan string yang akan ditambahkan ke LOB untuk meminimalkan jumlah panggilan ke
dbms_lob.append()
. - Hapus
dbms_output.put_line()
dari fungsi Anda. Jika konten LOB lebih besar dari 32K, ini akan menimbulkan pengecualian.
Juga, setelah Anda selesai mengirimkan LOB kembali ke env Java Anda, membebaskan LOB sementara . (Saya bukan orang Java, tidak bisa menulis potongan kode Java sendiri.)
Juga, Anda memiliki kesalahan konseptual dalam kode Java Anda; mendaftarkan kembalinya fungsi sebagai Types.VARCHAR
salah. Anda sebaiknya menggunakan Jenis CLOB khusus Oracle
. (Saya telah melihatnya di C#, Java juga harus memilikinya.)
Juga, ada satu masalah kinerja dengan solusi Anda. Fungsi Anda mengembalikan LOB. Dalam PL/SQL, setiap nilai fungsi dikembalikan ke pemanggilnya sebagai salinan dalam dari nilai dalam. Oleh karena itu, jika Anda mengembalikan LOB dari suatu fungsi, konten LOB diduplikasi di latar belakang dengan pencari LOB baru (/ pointer/referensi). Anda harus menggunakan Anda dapat mempertimbangkan untuk menggunakan prosedur tersimpan alih-alih fungsi dan meneruskan LOB ke Java sebagai out nocopy
parameter. Proc yang disimpan akan terlihat seperti ini:
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;
Bagaimana tampilan panggilan Java Anda, terserah Anda dan dokumen JDBC ; tetapi, yang pasti, LOB yang dikembalikan dengan cara ini berarti tidak ada konten latar belakang yang disalin. Tentu saja, kebutuhan untuk membebaskan LOB sementara yang dialokasikan tetap berlaku.