UTL_FILE 使用追加模式创建重复 headers
UTL_FILE using append mode creates repeating headers
如何在UTL_FILE包中使用"A"ppend模式,但只创建一个header(不再重复)?是否可以?我正在追加数据,但每次追加时,都会创建重复的 headers。
我的代码:
CREATE OR REPLACE PROCEDURE p_test AS
CURSOR c_test IS
select blah, blah from dual;
v_file UTL_FILE.FILE_TYPE;
v_header varchar2(25);
BEGIN
v_file := UTL_FILE.FOPEN(location => 'my_dir',
filename => 'filetest09102019.csv',
open_mode => 'A',
max_linesize => 32767);
If file exists = 0 then --using fgetattr; if I use 1, repeating headers will print
v_header := 'col1, col2, col3';
utl_file.put_line (v_file, v_header);
Else null; end if; --unfortunately headers did not print at all when false/0
FOR cur_rec IN c_test LOOP
UTL_FILE.PUT_LINE(v_file, data from c_test );
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(v_file);
END;
如果您多次调用此过程,则每次调用该过程时都会将 header 追加到文件中。
您可以先检查文件是否存在,然后再附加 header,例如使用 fgetattr 检测文件是否将被附加 Check if a file exists?
或者,修改您的代码,使其仅调用一次过程并一次写入所有数据,而不追加。
你可以通过一些设计来解决这个问题。目前,您有一个程序以追加模式打开文件,将文件头写入其中,然后将数据写入其中。您需要的是一个用于打开文件的子例程。这个程序将是
实现以下逻辑:
- 测试文件是否存在(like this one)
- 如果文件不存在,以写入模式创建文件,写入文件头,然后关闭文件
- 以追加模式打开文件。
您现有的过程现在只需调用上述例程并将数据写入打开的文件。这个东西(使用借来的和未经测试的代码):
CREATE OR REPLACE PROCEDURE p_test AS
CURSOR c_test IS
select blah, blah from dual;
v_file UTL_FILE.FILE_TYPE;
v_header varchar2(25) := 'col1, col2, col3';
function open_file (p_filename in varchar2
, p_dirname in varchar2
, p_header in varchar2
)
return UTL_FILE.FILE_TYPE
is
fh UTL_FILE.FILE_TYPE;
l_fexists boolean;
l_flen number;
l_bsize number;
l_res number(1);
begin
utl_file.fgetattr(upper(p_DirName), p_FileName, l_fexists, l_flen, l_bsize);
if not l_fexists then
fh := UTL_FILE.FOPEN(location => p_DirName,
filename => p_FileName,
open_mode => 'W',
max_linesize => 32767);
utl_file.put_line (fh, p_header);
utl_file.fclose(fh);
end if;
fh := UTL_FILE.FOPEN(location => p_DirName,
filename => p_FileName,
open_mode => 'A',
max_linesize => 32767);
return fh;
end open_file;
BEGIN
v_file := open_file 'my_dir', 'filetest09102019.csv', v_header);
FOR cur_rec IN c_test LOOP
UTL_FILE.PUT_LINE(v_file, data from c_test );
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(v_file);
END;
严格来说 open_file ()
在此示例中不需要私有过程。但总的来说,我认为将低级内容隐藏在单独的过程中是一种很好的做法,因为它使代码的主体更易于阅读。此外,我们经常希望在多个地方(针对不止一种类型的文件)执行此操作,因此封装起来很方便。
如何在UTL_FILE包中使用"A"ppend模式,但只创建一个header(不再重复)?是否可以?我正在追加数据,但每次追加时,都会创建重复的 headers。
我的代码:
CREATE OR REPLACE PROCEDURE p_test AS
CURSOR c_test IS
select blah, blah from dual;
v_file UTL_FILE.FILE_TYPE;
v_header varchar2(25);
BEGIN
v_file := UTL_FILE.FOPEN(location => 'my_dir',
filename => 'filetest09102019.csv',
open_mode => 'A',
max_linesize => 32767);
If file exists = 0 then --using fgetattr; if I use 1, repeating headers will print
v_header := 'col1, col2, col3';
utl_file.put_line (v_file, v_header);
Else null; end if; --unfortunately headers did not print at all when false/0
FOR cur_rec IN c_test LOOP
UTL_FILE.PUT_LINE(v_file, data from c_test );
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(v_file);
END;
如果您多次调用此过程,则每次调用该过程时都会将 header 追加到文件中。
您可以先检查文件是否存在,然后再附加 header,例如使用 fgetattr 检测文件是否将被附加 Check if a file exists?
或者,修改您的代码,使其仅调用一次过程并一次写入所有数据,而不追加。
你可以通过一些设计来解决这个问题。目前,您有一个程序以追加模式打开文件,将文件头写入其中,然后将数据写入其中。您需要的是一个用于打开文件的子例程。这个程序将是 实现以下逻辑:
- 测试文件是否存在(like this one)
- 如果文件不存在,以写入模式创建文件,写入文件头,然后关闭文件
- 以追加模式打开文件。
您现有的过程现在只需调用上述例程并将数据写入打开的文件。这个东西(使用借来的和未经测试的代码):
CREATE OR REPLACE PROCEDURE p_test AS
CURSOR c_test IS
select blah, blah from dual;
v_file UTL_FILE.FILE_TYPE;
v_header varchar2(25) := 'col1, col2, col3';
function open_file (p_filename in varchar2
, p_dirname in varchar2
, p_header in varchar2
)
return UTL_FILE.FILE_TYPE
is
fh UTL_FILE.FILE_TYPE;
l_fexists boolean;
l_flen number;
l_bsize number;
l_res number(1);
begin
utl_file.fgetattr(upper(p_DirName), p_FileName, l_fexists, l_flen, l_bsize);
if not l_fexists then
fh := UTL_FILE.FOPEN(location => p_DirName,
filename => p_FileName,
open_mode => 'W',
max_linesize => 32767);
utl_file.put_line (fh, p_header);
utl_file.fclose(fh);
end if;
fh := UTL_FILE.FOPEN(location => p_DirName,
filename => p_FileName,
open_mode => 'A',
max_linesize => 32767);
return fh;
end open_file;
BEGIN
v_file := open_file 'my_dir', 'filetest09102019.csv', v_header);
FOR cur_rec IN c_test LOOP
UTL_FILE.PUT_LINE(v_file, data from c_test );
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(v_file);
END;
严格来说 open_file ()
在此示例中不需要私有过程。但总的来说,我认为将低级内容隐藏在单独的过程中是一种很好的做法,因为它使代码的主体更易于阅读。此外,我们经常希望在多个地方(针对不止一种类型的文件)执行此操作,因此封装起来很方便。