使用UTL_FILE从Oracle表中提取BLOB文件,有些不压缩

时间:2015-04-06 18:22:11

标签: oracle compression blob utl-file

我有一个脚本可以从Oracle BLOB表中大量提取文档。这对于从Oracle到SQL的大量重写和数据库转换是必要的,其中文件将存储在SQL文件表中。由于文档必须位于文件系统上,我必须将它们取出并将其作为文件写出来。它适用于我的大部分文档。在我的桌子上敲了很多头之后,我终于想通了它,因为前端系统上有一些逻辑压缩了一些文件 - 尽管我真的无法弄清楚它的标准它这样做。无论如何,我在搜索和搜索之前都找不到任何类型的布尔检查,看看它们是否在Oracle BLOB表中被压缩,然后才提取它们。如果我尝试将它们解压缩,因为我提取它们,我会对那些没有压缩的错误产生错误。所以现在我想我可以通过解压缩来运行它们,然后捕获异常并通过导出而不进行解压缩来处理其他异常。我只是不能在我的脚本中使我的语法正确。这对我来说是一个新的挑战,我没有很多写这种脚本的经验,所以请原谅我的无知。这是我尝试解压缩所有错误时得到的错误,所以这就是我想要抓住的错误:

ORA-29294: A data error occurred during compression or uncompression.
ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 56
ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 226
ORA-06512: at "SYS.UTL_COMPRESS", line 89
ORA-06512: at line 21

这是脚本:

DECLARE

CURSOR C1 IS Select FILE_ID || '---' || substr(DOCUMENTLOCATION,1,instr  (DOCUMENTLOCATION,'.')-1)||'.doc' as FILE_NAME, FILE_BLOB, FILE_ID
From DOCUMENTS d inner join CASEJOURNAL c on d.FILE_ID = c.JOURNALENTRYID  where (JOURNAL_ENTRY_TYPE = 117 or JOURNAL_ENTRY_TYPE = 3) AND c.DOCUMENTLOCATION Is Not Null AND d.MIME_TYPE = 'application/msword' AND FILE_ID between 1 and 10000;

v_blob_uncomp   BLOB;
v_blob BLOB;
blob_length  INTEGER;
out_file      UTL_FILE.FILE_TYPE;
v_buffer    RAW(32767);
chunk_size    BINARY_INTEGER := 32767;
blob_position       INTEGER := 1;
filename varchar2(255); 

BEGIN
--Select BLOB file into variables
FOR I in C1 
LOOP
filename := i.FILE_NAME;
v_blob_uncomp := UTL_COMPRESS.LZ_UNCOMPRESS(i.FILE_BLOB);
v_blob := i.FILE_BLOB;

-- Define the output directory
out_file := UTL_FILE.FOPEN('fileloc',filename,'wb',chunk_size);

--Get length of BLOB file and save to variable.
blob_length := DBMS_LOB.getlength(v_blob);

-- Write the data to the file
        WHILE blob_position <= blob_length LOOP
        IF blob_position + chunk_size - 1 > blob_length THEN
        chunk_size := blob_length - blob_position + 1;
        END IF;
        DBMS_LOB.read(v_blob_uncomp, chunk_size, blob_position, v_buffer);
        UTL_FILE.PUT_RAW(out_file, v_buffer, TRUE);
        blob_position := blob_position + chunk_size;
        END LOOP;        
UTL_FILE.FCLOSE(out_file); 

END LOOP;
END;         

我知道当我不解压缩任何blob时脚本会起作用,但压缩的那些blob不会打开。当我对我知道压缩的某些文件进行解压缩时,它也有效。我只是试图让我的循环中的所有文件以某种方式工作。 TIA!

2 个答案:

答案 0 :(得分:3)

如果要在PL / SQL中捕获特定的Oracle错误代码,基本上有两个选项:

A)抓住所有例外情况;在处理程序中,测试错误消息是否与您要查找的错误消息匹配;如果是这样,处理它;如果没有,重新加注。这看起来像是:

BEGIN
  v_blob := := UTL_COMPRESS.LZ_UNCOMPRESS(i.FILE_BLOB);
EXCEPTION
  WHEN OTHERS THEN
    IF sqlerrm LIKE 'ORA-29294%' THEN
      v_blob := i.FILE_BLOB;
    ELSE
      RAISE;
    END IF;
END;

B)声明一个异常变量并将其映射到您关心的特定错误代码,然后只捕获该异常。这看起来像这样:

DECLARE
  compression_error  EXCEPTION;
  pragma exception_init ( compression_error, -29294 );
BEGIN
  v_blob := UTL_COMPRESS.LZ_UNCOMPRESS(i.FILE_BLOB);
EXCEPTION
  WHEN compression_error THEN
    v_blob := i.FILE_BLOB;
END;
无论哪种方式,我建议将其包装在一个函数中。

我还注意到,当您开始处理新BLOB时,显示的代码不会将blob_position重置为1.

答案 1 :(得分:1)

而不是&#34;尝试失败&#34;您可以考虑使用magic numbers: 从文件开头读取几个字节,如果它开始,用504B(PK)说,那么它很可能是zip存档。