2009-07-29 12 views
1

我正在編寫一個數據庫過程以將數據歸檔到包含BLOB的Oracle 9i表中。由於數據庫大小變得太大,我們的策略是將BLOB導出到文件系統(Windows 2000服務器),在那裏它們可以在磁帶上備份,然後截斷數據庫表。當爲BLOB使用utl_file.putraw()時,爲Oracle 9i輸出CRLF的解決方法?

這裏是我的過程,節省了BLOB磁盤:

 
     PROCEDURE blob_to_file 
     (
      -- BLOB to be written to file 
      pi_blob      IN BLOB, 

      -- Name of Oracle Directory object 
      pi_oracle_directory_name IN VARCHAR2, 

      -- Destination filename 
      pi_file_name    IN VARCHAR2 
    ) 
     IS 

     v_out_file  UTL_FILE.FILE_TYPE; 
     v_blob_len  INTEGER; 

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

     BEGIN 

     v_out_file := utl_file.fopen(
      location  => pi_oracle_directory_name, 
      filename  => pi_file_name, 
      open_mode  => 'W', 
      max_linesize => 32767); 

     v_blob_len := dbms_lob.getlength(pi_blob); 

     WHILE (v_pos < v_blob_len) LOOP 

     -- Ensure amount read is not less than remaining BLOB amount 
     IF (v_pos + v_amount) > (v_blob_len + 1) THEN 
      v_amount := v_blob_len - v_pos; 
     END IF; 

     -- Read chunk of BLOB into buffer 
     DBMS_LOB.read(
      lob_loc => pi_blob, 
      amount => v_amount, 
      offset => v_pos, 
      buffer => v_buffer); 

     -- Output the buffer as raw data into the file stream 
     utl_file.put_raw(
      file  => v_out_file, 
      buffer => v_buffer, 
      autoflush => true); 

     v_pos := v_pos + v_amount; 

     END LOOP; 

     -- Close the file 
     UTL_FILE.FCLOSE(v_out_file); 

     EXCEPTION 

     WHEN OTHERS THEN 
      -- Close the file if something goes wrong. 
      IF UTL_FILE.is_open(v_out_file) THEN 
      UTL_FILE.fclose(v_out_file); 
      END IF; 
      RAISE; 

    END blob_to_file; 

這是我的程序,通過該表中的BLOB和檔案迭代他們:

 
    PROCEDURE archive_letter_table 
     (
       -- Name of Oracle Directory object 
       pi_oracle_directory_name IN VARCHAR2 
    ) 
     IS 

     v_out_filename NVARCHAR2(100); 
     v_blob   BLOB; 

     CURSOR letter_cursor IS 
      SELECT 
      letter_id 
      ,template_ref 
      ,rtf 
      ,xml_data 
      ,row_version 
      ,file_name 
      ,document_type 
      ,document 
      ,business_entity_id 
      ,entity_type 
      ,date_created 
      ,sec_function_ref 
      ,user_account_ref 
      ,hsp 
      FROM 
      fusion.lms_letter; 

     BEGIN 

     FOR letter_cursor_row in letter_cursor LOOP 

      IF letter_cursor_row.document IS NOT NULL THEN 

      -- Retrieve BLOB and determine its size 
      v_blob := letter_cursor_row.document; 
      v_out_filename := CAST(letter_cursor_row.letter_id AS VARCHAR2) || '_' || letter_cursor_row.file_name; 

      -- Call procedure to write the BLOB to file   
      FILE_UTILS.blob_to_file(v_blob, pi_oracle_directory_name, v_out_filename); 

      END IF; 

     END LOOP; 

     TRUNCATE fusion.lms_letter; 

     END archive_lms_letter_table; 

我的2個問題是:

1)運行「archive_letter_table」過程後,保存到磁盤的文件包含CR和LF字符,而不僅僅是LF字符。我可以手動進行全局搜索/替換來修復它們,但需要一個自動PL/SQL解決方案。顯然有一個Oracle錯誤#2546782,其中「utl_file.put_raw()」的輸出由於插入了CR和LF而不正確。這幾乎肯定會導致我的問題。它提到本頁下方的底部: http://www.oracle.com/technology/sample_code/tech/pl_sql/htdocs/x/Utl_File/start.htm

有誰知道我可以去掉我的PL/SQL程序內這些CRLF的一種方式?

2)文件可以是PDF或RTF。保存的PDF效果很好(除了CRLF問題),但RTFS失敗,出現以下錯誤:

Error starting at line 5 in command: 
begin 
fusion.FUSION_ARCHIVE.archive_lms_letter_table('LMS_Letter_Archive_Dir'); 
end; 
Error report: 
ORA-29285: file write error 
ORA-06512: at "FUSION.FILE_UTILS", line 73 
ORA-06512: at "FUSION.FUSION_ARCHIVE", line 59 
ORA-06512: at line 2 
29285. 00000 - "file write error" 
*Cause: Failed to write to, flush, or close a file. 
*Action: Verify that the file exists, that it is accessible, and that 
      it is open in write or append mode.

的PDF文件範圍69KB之間大小219KB,而RTF 應該 633KB。但是由於上面的錯誤,它最終在磁盤上是7KB,顯然無法讀取。通過比較原始的RTF和我的程序試圖保存到磁盤上的RTF,我可以看到我的程序無法保存文檔的最後一行(這顯然很長​​... 626KB)。我懷疑這是另一回事put_raw不處理這麼長的行。

有沒有人有任何線索如何解決這個問題?

如果您只有一個問題的解決方案,請隨時予以答覆。任何幫助不勝感激。

回答

1

至於你CR/LF問題,好像you have been Oracled(不好的事情,很明顯...):

At the time of this writing, there are no workarounds nor is Oracle considering back-porting a fix for Oracle9i.

您可以通過深入研究這些Ask Tom answers獲得更深入的瞭解。在你的情況下,我想開發一個Java包將是一個值得考慮的選擇。

+0

Oracle 9不再完全支持。總理支持已經結束。 – Theo 2009-07-29 09:23:36

+0

感謝您的回覆Mac。 是的,我想我們可能需要編寫一個應用程序來處理導出。我們是一家.NET商店,希望ODP.NET能夠處理它!否則,我們正在研究Java解決方案。 – Ashby 2009-07-30 01:03:37

0

鑑於你正在做什麼與數據(即試圖從數據庫中刪除它)什麼是將表(作爲BLOBs)複製到以後的數據庫版本(或Linux或其他非Windows版本)的可行性是什麼? 。 然後你可以從那裏運行提取。

+0

謝謝你的建議加里。這是我將研究的內容......只是關於是否有正在使用的版本10或11 Oracle服務器的問題。懷疑我會被驅趕寫一個應用程序的路徑。 – Ashby 2009-07-30 01:04:37

1

我們有一個奇怪的,試圖處理MAC輸出,它只是使用CR的。

我們用一個CR將一個文件作爲BLOB加載到數據庫,這沒問題。

當我們試圖從BLOB中寫出來的時候,它出現了與您獲得的代碼相同的錯誤!

解決方案是在插入blob之前將所有CR替換爲CR LF。

然後有趣的是,當Oracle寫出來(DB在UNIX上)時,它只是寫出LF的。

然後,在交付用戶之前,我們用實際輸出文件中的CR替換LF的!

相關問題