sql >> データベース >  >> RDS >> Oracle

ORA-22275:無効なLOBロケーターが指定されました

    はい。 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;
    
    1. カーソルを開いたり、フェッチしたり、閉じたりする必要はありません。通常のカーソルループは問題なく動作します(内部での暗黙的なバルクフェッチのおかげで、さらに良くはありません)。
    2. 一時LOBをキャッシュ済みとして明示的に宣言します(cache => true;あなたがすでに持っているように)。これにより、データチャンクがディスクに追加されるのではなく、メモリ内のLOBに追加されます(cache => false
    3. dbms_lob.append()への呼び出し回数を最小限に抑えるために、LOBに追加する文字列を連結します。 。
    4. 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を解放する必要性は引き続き適用されます。



    1. mysqlコマンドラインで高精度のクエリ時間を確認するにはどうすればよいですか?

    2. MySQLでクエリを最適化および修正するためのヘルプを求めるにはどうすればよいですか?

    3. SQL結合2テーブル

    4. Mysqlは、ストアドプロシージャで一時的にauto_increment列を無効にします