当前位置: 首页 > 知识库问答 >
问题:

在Oracle中向文件写入CLOB

公冶才
2023-03-14

当执行以下PL/SQL代码时,CLOB将作为文本文件写入目录。但是,我认为整个CLOB没有输出,因为当我试图解码时,图像被破坏了(只有图像的上部会出现)。我在一个小图像(11K)上运行它,它工作得很好。我还监测到l_pos正在正确地增加,所以它似乎正在读取CLOB(32KB)的每个块,我做错了什么?

我使用的是Oracle11g Express Edition(XE)和SQL Developer。以下是错误和代码

create or replace PROCEDURE c2F
 IS
   p_filename       VARCHAR2(100);
   p_dir            VARCHAR2(100) := 'IO_DIR';
   c_amount         CONSTANT BINARY_INTEGER := 32767;
   l_buffer         VARCHAR2(32767);
   l_chr10          PLS_INTEGER;
   l_clobLen        PLS_INTEGER;
   l_fHandler       sys.UTL_FILE.FILE_TYPE;
   l_pos            PLS_INTEGER    := 1;
   v_blob           BLOB;
   p_clob           CLOB;

 BEGIN
  dbms_output.put_line('Start Time: ' || TO_CHAR(sysdate,('YYYY/MM/DD hh24:Mi:ssss')));

  FOR i IN
    (SELECT student_no,
            image v_blob,
            encdec_base64.encode_base64(image) p_clob 
    FROM student_t1
    WHERE student_no =200601022
  ) loop

   IF (dbms_lob.isopen(i.p_clob) = 0) THEN
      dbms_lob.open(i.p_clob,dbms_lob.lob_readonly);
    END IF;
   l_pos      := 1;
   p_filename := i.student_no || '.txt';
   l_clobLen  := DBMS_LOB.GETLENGTH(i.p_clob);
   l_fHandler := sys.UTL_FILE.FOPEN(p_dir, p_fileName,'WB',c_amount);
   l_buffer := DBMS_LOB.SUBSTR(i.p_clob, c_amount, l_pos);

  WHILE l_pos < l_clobLen LOOP
     l_buffer := DBMS_LOB.SUBSTR(i.p_clob, c_amount, l_pos);

     EXIT WHEN l_buffer IS NULL;
     UTL_FILE.put_raw(l_fHandler,utl_raw.cast_to_raw(l_buffer));
     l_pos := l_pos + LEAST(LENGTH(l_buffer)+1,c_amount);
     UTL_FILE.FFLUSH(l_fHandler);
     END LOOP;
  END LOOP;
   sys.UTL_FILE.FCLOSE(l_fHandler);

 EXCEPTION
  WHEN OTHERS THEN
   IF UTL_FILE.IS_OPEN(l_fHandler) THEN
   UTL_FILE.FCLOSE(l_fHandler);
   END IF;
   RAISE;
dbms_output.put_line('End Time: ' || TO_CHAR(sysdate,('YYYY/MM/DD hh24:Mi:ssss')));
 END; 

共有1个答案

卢伟志
2023-03-14

尝试使用比32767小的缓冲区,特别是大小不超过8191的缓冲区。

据我所知,如果缓冲区大小超过8191个字符,dbms_lob.substr并不总是正常运行。如果要求它读取(比方说)10000个字符,它可能只能从LOB读取8191个字符,但它会返回给您一个10000个字符的长字符串,其中前8191个字符是它从LOB读取的字符,其他1809个字符是之前发生的字符(例如,上次调用dbms_lob.substr)。如果缓冲区大小为8191个字符或更小,则不会出现此问题,dbms_lob.substr返回您要求的字符数。

我不明白为什么这个函数会这样做。似乎很奇怪。我只能断定是数据库中的bug。它是特定于Oracle11g还是XE,我不能说。

dbms_lob.substr的Oracle文档包括以下用法说明,它没有解释问题,但确实提到了数字8191:

  • dbms_lob.substr将根据LOB中存储的字符返回8191个或更多字符。如果由于字符字节大小超过可用缓冲区而没有返回所有字符,则用户应该使用新的偏移量调用dbms_lob.substr来读取剩余字符,或者html" target="_blank">循环调用子程序,直到提取完所有数据。
 类似资料:
  • ===================trace================================

  • 问题内容: 我一直在尝试找到一种使用Node.js时写入文件的方法,但是没有成功。我怎样才能做到这一点? 问题答案: 文件系统API中有很多详细信息。最常见的方法是:

  • 我在Windows10和vscode上使用Python 3.8.1。

  • 问题内容: 我一直在尝试找到一种使用Node.js时写入文件的方法,但是没有成功。我怎样才能做到这一点? 问题答案: 文件系统API中有很多详细信息。最常见的方法是:

  • 我使用ubuntu 16.04。我想在有cassandra java api的程序中编写登录文件。日志可以写在java控制台中,但不能写在文件中。 我的节目: 还有我的log4j。属性:

  • 本文向大家介绍如何在Oracle中导入dmp文件,包括了如何在Oracle中导入dmp文件的使用技巧和注意事项,需要的朋友参考一下 项目开始拿到了dmp文件,数据库用的是10g的,但是尽然没导成功,后来想可能导出的时候用11导出的,决定试一下。 正好自己的机器是11的客户端,结果不识别imp命令,到安装目录下的bin文件夹下看尽然没有imp执行文件。可能装客户端的时候没选管理者装。 怎么办呢,从别