1

BLOBを含むOracle9iテーブルにデータをアーカイブするデータベースプロシージャを作成しています。データベースのサイズが大きくなりすぎたため、BLOBをファイルシステム(Windows 2000サーバー)にエクスポートして、テープにバックアップしてから、データベーステーブルを切り捨てることをお勧めします。

BLOBをディスクに保存する手順は次のとおりです。

      手順blob_to_file
      ((
          --ファイルに書き込まれるBLOB
          pi_blob IN BLOB、

          --OracleDirectoryオブジェクトの名前
          pi_oracle_directory_name IN VARCHAR2、

          -宛先ファイル名
          pi_file_name IN VARCHAR2
      )。
      は

        v_out_file UTL_FILE.FILE_TYPE;
        v_blob_len INTEGER;

        v_buffer RAW(32767);
        v_amount BINARY_INTEGER:= 32767;
        v_pos INTEGER:= 1;

      始める

      v_out_file:= utl_file.fopen(
          場所=>pi_oracle_directory_name、
          ファイル名=>pi_file_name、
          open_mode =>'W'、
          max_linesize => 32767);

      v_blob_len:= dbms_lob.getlength(pi_blob);

      WHILE(v_pos <v_blob_len)LOOP

        -読み取られた量が残りのBLOB量以上であることを確認します
        IF(v_pos + v_amount)>(v_blob_len + 1)THEN
          v_amount:= v_blob_len-v_pos;
        END IF;

        --BLOBのチャンクをバッファに読み込みます
        DBMS_LOB.read(
          lob_loc => pi_blob、
          金額=>v_amount、
          オフセット=>v_pos、
          buffer => v_buffer);

        -バッファを生データとしてファイルストリームに出力します
        utl_file.put_raw(
          ファイル=>v_out_file、
          buffer => v_buffer、
          自動フラッシュ=>true);

        v_pos:= v_pos + v_amount;

      ループを終了します。

      -ファイルを閉じます
      UTL_FILE.FCLOSE(v_out_file);

      例外

        他の人が
          -問題が発生した場合はファイルを閉じます。
          IF UTL_FILE.is_open(v_out_file)THEN
            UTL_FILE.fclose(v_out_file);
          END IF;
          高める;

    END blob_to_file;

そして、これがテーブル内のBLOBを反復処理し、それらをアーカイブする私の手順です。

    手順archive_letter_table
      ((
              --OracleDirectoryオブジェクトの名前
              pi_oracle_directory_name IN VARCHAR2
      )。
      は

        v_out_filename NVARCHAR2(100);
        v_blob BLOB;

        CURSOR letter_cursor IS
          選択する
            letter_id
            、template_ref
            、rtf
            、xml_data
            、row_version
            、ファイル名
            、ドキュメントタイプ
            、資料
            、business_entity_id
            、entity_type
            、date_created
            、sec_function_ref
            、user_account_ref
            、hsp
          から
            Fusion.lms_letter;

      始める

        letter_cursorLOOPのletter_cursor_rowの場合

          letter_cursor_row.documentがNULLでない場合

            --BLOBを取得し、そのサイズを決定します
            v_blob:= letter_cursor_row.document;
            v_out_filename:= CAST(letter_cursor_row.letter_id AS VARCHAR2)|| '_' || letter_cursor_row.file_name;

            --プロシージャを呼び出してBLOBをファイルに書き込みます        
            FILE_UTILS.blob_to_file(v_blob、pi_oracle_directory_name、v_out_filename);

          END IF;

        ループを終了します。

        TRUNCATEfusion.lms_letter;

      END archive_lms_letter_table;

私の2つの問題は次のとおりです。

1)「archive_letter_table」プロシージャを実行した後、ディスクに保存されたファイルには、LF文字だけでなくCR文字とLF文字が含まれています。グローバル検索/置換を手動で実行して修正できますが、自動化されたPL/SQLソリューションが必要です。どうやら、CRとLFを挿入したために、「utl_file.put_raw()」からの出力が正しくないOracleのバグ#2546782があります。これはほぼ間違いなく私の問題を引き起こしているようです。このページの下部に記載されています: http ://www.oracle.com/technology/sample_code/tech/pl_sql/htdocs/x/Utl_File/start.htm

PL / SQLプロシージャ内のこれらのCRLFを取り除く方法を知っている人はいますか?

2)ファイルはPDFまたはRTFのいずれかです。PDFの保存は(CRLFの問題を除いて)うまく機能しますが、RTFは次のエラーで失敗します。

コマンドの5行目からのエラー:
始める
fusion.FUSION_ARCHIVE.archive_lms_letter_table('LMS_Letter_Archive_Dir');
終わり;
エラーレポート:
ORA-29285:ファイル書き込みエラー
ORA-06512:「FUSION.FILE_UTILS」の73行目
ORA-06512:「FUSION.FUSION_ARCHIVE」の59行目
ORA-06512:2行目
29285.00000-「ファイル書き込みエラー」
*原因:ファイルへの書き込み、フラッシュ、またはファイルのクローズに失敗しました。
*アクション:ファイルが存在すること、アクセス可能であること、およびファイルがアクセス可能であることを確認してください。
           書き込みモードまたは追加モードで開いています。

PDFファイルのサイズは69KBから219KBの範囲ですが、RTFは633KBである必要があります。ただし、上記のエラーのため、ディスク上で7KBになり、明らかに読み取ることができません。元のRTFを、プロシージャがディスクに保存しようとしているRTFと比較すると、プロシージャがドキュメントの最後の行(明らかに非常に長い... 626KB)を保存できないことがわかります。これは、put_rawが行をそれほど長く処理しないことと関係があるのではないかと思います。

この問題を回避する方法について誰かが手がかりを持っていますか?

問題の1つだけの解決策がある場合は、遠慮なく対応してください。どんな助けでも大歓迎です。

4

3 に答える 3

1

CR のみを使用する MAC 出力を処理しようとすると、奇妙な問題が発生しました。

CR のみを含むファイルを BLOB としてデータベースにロードしましたが、これで問題ありませんでした。

BLOB から書き出そうとすると、取得したのと同じコードでエラーが発生しました!

解決策は、ブロブに挿入する前に、すべての CR を CR LF に置き換えることでした。

興味深いことに、Oracle がそれを書き出すとき (DB は UNIX 上にあります)、単に LF を書き出すだけです。

次に、ユーザーを配信する前に、実際の出力ファイルで LF を CR に置き換えます。

于 2010-02-04T12:35:43.897 に答える
1

CR/LF の問題に関しては、Oracledのようです(明らかに悪いことです...)。

この記事の執筆時点では、回避策はなく、Oracle は Oracle9i の修正をバックポートすることを検討していません。

これらのAsk Tom の回答を掘り下げることで、より多くの洞察を得ることができます。あなたの場合、Java パッケージの開発は検討に値するオプションだと思います。

于 2009-07-29T09:07:27.503 に答える
0

データを使って何をしているのか(つまり、データベースからデータを削除しようとしているのか)、テーブルを(BLOBとして)新しいデータベースバージョン(またはLinuxやその他のWindows以外のバージョン)にコピーする可能性はどのくらいありますか。次に、そこから抽出を実行できます。

于 2009-07-29T22:40:44.457 に答える