3

Oracle BLOB テーブルからドキュメントをまとめて抽出するスクリプトがあります。これは、ファイルが SQL ファイル テーブルに格納される場合に、Oracle から SQL への大規模な書き換えとデータベース変換に必要です。ドキュメントはファイル システムに保存する必要があるため、それらを取り出してファイルとして書き出す必要があります。ほとんどのドキュメントでうまく機能します。机に頭をぶつけた後、フロントエンドシステムに一部のドキュメントを圧縮するロジックがあるためであることが最終的にわかりました. とにかく、検索して検索しましたが、それらを抽出する前に、Oracle BLOB テーブル内で圧縮されているかどうかを確認するためのブール値チェックが見つかりません。それらを抽出しているときにそれらをすべて解凍しようとすると、圧縮されていないものでエラーが発生します。だから今、私はそれらすべてを解凍して実行し、例外をキャッチして、解凍せずにエクスポートすることで他のものを処理できると考えています。スクリプトで正しい構文を取得できません。これは私にとって新しい挑戦であり、この種のスクリプトを書いた経験はあまりないので、私の無知を許してください。それらすべてを解凍しようとしたときに発生するエラーは次のとおりです。これがキャッチしようとしているものです。この種のスクリプトを書いた経験は山ほどあるので、私の無知をお許しください。それらすべてを解凍しようとしたときに発生するエラーは次のとおりです。これがキャッチしようとしているものです。この種のスクリプトを書いた経験は山ほどあるので、私の無知をお許しください。それらすべてを解凍しようとしたときに発生するエラーは次のとおりです。これがキャッチしようとしているものです。

ORA-29294: A data error occurred during compression or uncompression.
ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 56
ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 226
ORA-06512: at "SYS.UTL_COMPRESS", line 89
ORA-06512: at line 21

スクリプトは次のとおりです。

DECLARE

CURSOR C1 IS Select FILE_ID || '---' || substr(DOCUMENTLOCATION,1,instr  (DOCUMENTLOCATION,'.')-1)||'.doc' as FILE_NAME, FILE_BLOB, FILE_ID
From DOCUMENTS d inner join CASEJOURNAL c on d.FILE_ID = c.JOURNALENTRYID  where (JOURNAL_ENTRY_TYPE = 117 or JOURNAL_ENTRY_TYPE = 3) AND c.DOCUMENTLOCATION Is Not Null AND d.MIME_TYPE = 'application/msword' AND FILE_ID between 1 and 10000;

v_blob_uncomp   BLOB;
v_blob BLOB;
blob_length  INTEGER;
out_file      UTL_FILE.FILE_TYPE;
v_buffer    RAW(32767);
chunk_size    BINARY_INTEGER := 32767;
blob_position       INTEGER := 1;
filename varchar2(255); 

BEGIN
--Select BLOB file into variables
FOR I in C1 
LOOP
filename := i.FILE_NAME;
v_blob_uncomp := UTL_COMPRESS.LZ_UNCOMPRESS(i.FILE_BLOB);
v_blob := i.FILE_BLOB;

-- Define the output directory
out_file := UTL_FILE.FOPEN('fileloc',filename,'wb',chunk_size);

--Get length of BLOB file and save to variable.
blob_length := DBMS_LOB.getlength(v_blob);

-- Write the data to the file
        WHILE blob_position <= blob_length LOOP
        IF blob_position + chunk_size - 1 > blob_length THEN
        chunk_size := blob_length - blob_position + 1;
        END IF;
        DBMS_LOB.read(v_blob_uncomp, chunk_size, blob_position, v_buffer);
        UTL_FILE.PUT_RAW(out_file, v_buffer, TRUE);
        blob_position := blob_position + chunk_size;
        END LOOP;        
UTL_FILE.FCLOSE(out_file); 

END LOOP;
END;         

BLOB を解凍しないとスクリプトが機能することはわかっていますが、圧縮された BLOB は開きません。また、圧縮されていることがわかっている特定のファイルを解凍するときにも機能します。どういうわけか、すべてのファイルのループ内でこれを機能させようとしています。ティア!

4

2 に答える 2

3

PL/SQL で特定の Oracle エラー コードをキャッチする場合、基本的に次の 2 つのオプションがあります。

A) すべての例外をキャッチします。ハンドラーで、エラー メッセージが探しているものと一致するかどうかをテストします。もしそうなら、それを処理してください。そうでない場合は、再度上げます。これは次のようになります。

BEGIN
  v_blob := := UTL_COMPRESS.LZ_UNCOMPRESS(i.FILE_BLOB);
EXCEPTION
  WHEN OTHERS THEN
    IF sqlerrm LIKE 'ORA-29294%' THEN
      v_blob := i.FILE_BLOB;
    ELSE
      RAISE;
    END IF;
END;

B) 例外変数を宣言し、関心のある特定のエラー コードにマップしてから、その例外のみをキャッチします。これは次のようになります。

DECLARE
  compression_error  EXCEPTION;
  pragma exception_init ( compression_error, -29294 );
BEGIN
  v_blob := UTL_COMPRESS.LZ_UNCOMPRESS(i.FILE_BLOB);
EXCEPTION
  WHEN compression_error THEN
    v_blob := i.FILE_BLOB;
END;

いずれにせよ、これを関数でラップすることをお勧めします。

blob_positionまた、表示されているコードは、新しい BLOB の処理を​​開始しても 1 にリセットされないことにも注意してください。

于 2015-04-06T19:28:35.053 に答える