我正在编写一个数据库过程来归档包含 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 没有处理这么长时间的行有关。
有没有人知道如何解决这个问题?
如果您只有其中一个问题的解决方案,请随时回复。非常感谢任何帮助。
灰