我正在編寫一個數據庫過程以將數據歸檔到包含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不處理這麼長的行。
有沒有人有任何線索如何解決這個問題?
如果您只有一個問題的解決方案,請隨時予以答覆。任何幫助不勝感激。
灰
Oracle 9不再完全支持。總理支持已經結束。 – Theo 2009-07-29 09:23:36
感謝您的回覆Mac。 是的,我想我們可能需要編寫一個應用程序來處理導出。我們是一家.NET商店,希望ODP.NET能夠處理它!否則,我們正在研究Java解決方案。 – Ashby 2009-07-30 01:03:37