Write CLOB into HTML file

打算写个存储过程从数据库中抓取想要的SQL语句,然后通过邮件方式发出来。因为发送的邮件默认是文本格式,不太好看,因此想换成html格式。于是乎我要生成一个HTML字符串。本来是想直接放到附件中,但是因为生成的内容可能太大,放到附件不太合适,就需要改成写到文件中。

于是乎,就需要实现把CLOB写入文件的操作,不幸的是遇到不少麻烦。

1. UTL_FILE

写文件,第一反应就是调用UTL_FILE包。但是在调用UTL_FILE.PUT_LINE的时候,老是报如下错误...

ORA-29285: file write error

搞了半天才发现问题出在调用PUT_LINE的时候传入的字符串长度超过了32765个字符!

查看文档看看关于PUT_LINE的说明...

PUT_LINE Procedure

This procedure writes the text string stored in the buffer parameter to the open file identified by the file handle. The file must be open for write operations. PUT_LINE terminates the line with the platform-specific line terminator character or characters.

See also "PUT_LINE_NCHAR Procedure".

Syntax

UTL_FILE.PUT_LINE (
   file      IN FILE_TYPE,
   buffer    IN VARCHAR2,
   autoflush IN BOOLEAN DEFAULT FALSE);

Parameters

Table 168-20 PUT_LINE Procedure Parameters

ParametersDescription

file

Active file handle returned by an FOPEN call.

buffer

Text buffer that contains the lines to be written to the file.

autoflush

Flushes the buffer to disk after the WRITE.

 

没有看到任何关于buffer长度限制的说明,但是注意到UTL_FILE.FOPEN的说明就会发现问题所在了。

FOPEN Function

This function opens a file. You can specify the maximum line size and have a maximum of 50 files open simultaneously. See also FOPEN_NCHAR Function.

Syntax

UTL_FILE.FOPEN (
   location     IN VARCHAR2,
   filename     IN VARCHAR2,
   open_mode    IN VARCHAR2,
   max_linesize IN BINARY_INTEGER) 
  RETURN file_type;

Parameters

Table 168-8 FOPEN Function Parameters

ParameterDescription

location

Directory location of file. This string is a directory object name and is case sensitive. The default is uppercase. Read privileges must be granted on this directory object for the UTL_FILE user to run FOPEN.

filename

File name, including extension (file type), without directory path. If a directory path is given as a part of the filename, it is ignored by FOPEN. On Unix, the filename cannot end with /.

open_mode

Specifies how the file is opened. Modes include:

r -- read text

w -- write text

a -- append text

rb -- read byte mode

wb -- write byte mode

ab -- append byte mode

If you try to open a file specifying 'a' or 'ab' for open_mode but the file does not exist, the file is created in write mode.

max_linesize

Maximum number of characters for each line, including the newline character, for this file (minimum value 1, maximum value 32767). If unspecified, Oracle supplies a default value of 1024.

 

注意到参数max_linesize最大值为32767个字符(默认为1024), 同时这个限制中包含了换行符(在windows下测试是两个字符长)的字符数。因此在调用put_line的时候传入的字符串长度不能超过32765!

可以进行简单测试...

DECLARE 
l_fHandle UTL_FILE.FILE_TYPE;
l_linesize PLS_INTEGER := 32767; -- Change it to 32765
BEGIN

l_fHandle := UTL_FILE.FOPEN('SQL_REPORT_DIR', 'test_file2.txt', 'w', 32767);

UTL_FILE.PUT_LINE(l_fHandle, rpad('x', l_linesize, 'x'), true);

UTL_FILE.FCLOSE(l_fHandle);
EXCEPTION
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(l_fHandle) THEN
UTL_FILE.FCLOSE(l_fHandle);
END IF;
RAISE;
END;
/


当把l_linesize改到32765以下的时候,上面的代码才可以正常执行。

这个问题虽然接解决了,但是因为我是想生成HTML文件,因此生成的CLOB是包含HTML标签的, 通过PUT_LINE这样写入文件的话,有可能会把标签拆成了两行,结果造成HTML文件不能正常显示。改咋办呢?

2. DBMS_XSLPROCESSOR.CLOB2FILE


无意中看到“Oracle-Developer.net"中有篇文章提到用DBMS_XSLPROCESSOR.CLOB2FILE一次把CLOB写入到文件中,试了下,相当容易!而且不会像put_line那样会截断CLOB一点点写入,所以最后生成的HTML文件可以正常显示出来。调用方式如下...

DBMS_XSLPROCESSOR.CLOB2FILE(p_clob_content, p_directory_name, TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') || '_SBVR.html');

原文地址:https://www.cnblogs.com/fangwenyu/p/2398625.html