はい。 LOBは、メモリ/ディスクストレージへのポインタ/参照です。最初にストレージを「memalloc()」(...初期化)し、ポインタ/参照をLOB変数に割り当てる必要があります。それがdbms_lob.createTemporary()
です です。有効なLOBロケーターを使用してLOB変数を初期化しない限り、そのLOB変数に対するすべての操作はORA-22275: invalid LOB locator specified
で失敗します。 。
機能強化: PL / SQL関数を少しリファクタリングします:(そして、last_60_cpu_cursor
にダミークエリを使用したことに注意してください カーソル。カーソルを再利用しないでください。独自のカーソルを使用してください。 :-))
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;
- カーソルを開いたり、フェッチしたり、閉じたりする必要はありません。通常のカーソルループは問題なく動作します(内部での暗黙的なバルクフェッチのおかげで、さらに良くはありません)。
- 一時LOBをキャッシュ済みとして明示的に宣言します(
cache => true
;あなたがすでに持っているように)。これにより、データチャンクがディスクに追加されるのではなく、メモリ内のLOBに追加されます(cache => false
。 -
dbms_lob.append()
への呼び出し回数を最小限に抑えるために、LOBに追加する文字列を連結します。 。 -
dbms_output.put_line()
を削除します あなたの関数から。 32Kを超えるLOBコンテンツの場合、とにかく例外がスローされます。
また、LOBをJava環境に戻す作業が完了したら、一時LOBを解放する 。 (私はJavaの人ではないので、Javaコードスニペットを自分で書くことはできません。)
また、Javaコードに概念上のエラーがあります。関数の戻り値をTypes.VARCHAR
として登録します 間違っている。むしろ、Oracleの専用CLOBタイプ
を使用する必要があります。 。 (C#でそれらを見たことがありますが、Javaにもそれらが必要です。)
また、ソリューションにはパフォーマンスの問題が1つあります。関数はLOBを返します。 PL / SQLでは、各関数値は内部値のディープコピーとして呼び出し元に返されます。したがって、関数からLOBを返す場合、LOBの内容は新しいLOBロケーター(/ポインター/参照)を使用してバックグラウンドで複製されます。使用する必要があります 関数の代わりにストアドプロシージャを使用して、LOBをout nocopy
としてJavaに渡すことを検討してください。 パラメータ。ストアドプロシージャは次のようになります。
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;
Java呼び出しはどのように見えるかは、あなたとJDBCドキュメント ;しかし、確かに、この方法で返されたLOBは、バックグラウンドコンテンツのコピーがないことを意味します。もちろん、割り当てられた一時LOBを解放する必要性は引き続き適用されます。