我读过这篇关于调整 UTL_FILE的文章
从技术上讲,该方法是在大小小于缓冲区的最大长度时连接记录,并在长度更大时写入整个缓冲区
网站摘录(代码):
IF LENGTH(v_buffer) + c_eollen + LENGTH(r.csv) <= c_maxline THEN
v_buffer := v_buffer || c_eol || r.csv;
ELSE
IF v_buffer IS NOT NULL THEN
UTL_FILE.PUT_LINE(v_file, v_buffer);
END IF;
v_buffer := r.csv;
END IF;
所以,我决定把这个移到一个函数中
-- constants
C_CHR CONSTANT VARCHAR2(2) := CHR(10);
C_CHRLEN CONSTANT PLS_INTEGER := LENGTH(C_CHR);
C_MAXLEN CONSTANT PLS_INTEGER := 32767;
function FN_GET_BUFFER(p_rec IN VARCHAR2, p_buffer IN VARCHAR2) RETURN VARCHAR2
is
begin
IF LENGTH(p_buffer) + C_CHRLEN + LENGTH(p_rec) <= C_MAXLEN THEN
RETURN p_buffer || C_CHR || p_rec;
ELSE
IF p_buffer IS NOT NULL THEN
RETURN p_buffer;
END IF;
RETURN p_rec;
END IF;
end FN_GET_BUFFER;
这就是我调用我的函数的方式,它不能按预期工作..
procedure export as
l_tmp_file_name VARCHAR2(30);
l_csv_file_name VARCHAR2(30);
l_file UTL_FILE.FILE_TYPE;
l_buffer VARCHAR2(32767);
CURSOR cur_table
IS
SELECT * FROM table
begin
l_tmp_file_name := 'file.tmp';
BEGIN
l_file := UTL_FILE.FOPEN(C_DIRECTORY_PATH, l_tmp_file_name,'A',C_MAXLEN);
FOR rec IN cur_table
LOOP
l_rec := CONVERT(rec.id || ',' || rec.user ,'AL32UTF8');
l_buffer := l_buffer || FN_GET_BUFFER(l_rec, l_buffer);
if l_buffer is NOT NULL then
UTL_FILE.PUT_LINE(l_file, l_buffer);
l_buffer := NULL;
end if;
END LOOP rec;
UTL_FILE.FCLOSE(l_file);
l_csv_file_name := 'file.csv';
UTL_FILE.FRENAME(src_location => C_DIRECTORY_PATH, src_filename => l_tmp_file_name, dest_location => C_DIRECTORY_PATH, dest_filename => l_csv_file_name, overwrite => FALSE);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(l_file);
UTL_FILE.FREMOVE(location => C_DIRECTORY_PATH, filename => l_tmp_file_name);
END;
end export;
问题是我得到
1,user1
2,user2
3,user3
4,user4
5,
user5
6,user6
7,user7
8,user8
9,user9
10,user10
11,user11
12,user12
13,user13
14,
user14
15,user15
16,user16
17,user17
18,user19
如您所见,在 4 条记录之后,缓冲区“已满”,因此它写入的是 user14 的缓冲区,而不是全部写入同一行
谢谢