我正在编写一个数据库过程来归档包含 BLOB 的 Oracle 9i 表中的数据。由于数据库变得太大,我们的策略是将 BLOB 导出到文件系统(Windows 2000 服务器),在那里可以将它们备份到磁带上,然后截断数据库表。
这是我将 BLOB 保存到磁盘的过程:
程序 blob_to_file ( -- 要写入文件的 BLOB pi_blob 在 BLOB 中, -- Oracle 目录对象的名称 pi_oracle_directory_name IN VARCHAR2, -- 目标文件名 pi_file_name IN VARCHAR2 ) 是 v_out_file UTL_FILE.FILE_TYPE; v_blob_len 整数; v_buffer RAW(32767); v_amount BINARY_INTEGER := 32767; v_pos 整数:= 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) 循环 -- 确保读取的数量不小于剩余的 BLOB 数量 如果 (v_pos + v_amount) > (v_blob_len + 1) 那么 v_amount := v_blob_len - v_pos; 万一; -- 将 BLOB 块读入缓冲区 DBMS_LOB.read( lob_loc => pi_blob, 金额 => v_amount, 偏移量 => v_pos, 缓冲区 => v_buffer); -- 将缓冲区作为原始数据输出到文件流中 utl_file.put_raw( 文件 => v_out_file, 缓冲区 => v_buffer, 自动刷新 => 真); v_pos := v_pos + v_amount; 结束循环; -- 关闭文件 UTL_FILE.FCLOSE(v_out_file); 例外 其他时候 -- 如果出现问题,请关闭文件。 如果 UTL_FILE.is_open(v_out_file) 那么 UTL_FILE.fclose(v_out_file); 万一; 增加; 结束blob_to_file;
这是我的过程,它遍历表中的 BLOB 并将它们归档:
程序 archive_letter_table ( -- Oracle 目录对象的名称 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 ,文件名 ,document_type ,文档 ,business_entity_id ,实体类型 ,创建日期 ,sec_function_ref ,user_account_ref ,热休克蛋白 从 fusion.lms_letter; 开始 FOR letter_cursor_row in letter_cursor 循环 如果 letter_cursor_row.document 不是 NULL THEN -- 检索 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); 万一; 结束循环; 截断 fusion.lms_letter; 结束存档_lms_letter_table;
我的两个问题是:
1) 运行“archive_letter_table”过程后,保存到磁盘的文件包含 CR 和 LF 字符,而不仅仅是 LF 字符。我可以手动进行全局搜索/替换来修复它们,但需要一个自动化的 PL/SQL 解决方案。显然有一个 Oracle 错误 #2546782,由于插入 CR 和 LF,“utl_file.put_raw()”的输出不正确。这几乎可以肯定似乎是导致我的问题。它在本页底部提到: 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 没有处理这么长时间的行有关。
有没有人知道如何解决这个问题?
如果您只有其中一个问题的解决方案,请随时回复。非常感谢任何帮助。
灰