Sql 在循环中调用UTL_FILE.put时发生UTL_FILE.WRITE_错误
我的PL/SQL过程中有以下代码,我在while循环中的API_XXX.put(它调用Sql 在循环中调用UTL_FILE.put时发生UTL_FILE.WRITE_错误,sql,oracle,plsql,utl-file,Sql,Oracle,Plsql,Utl File,我的PL/SQL过程中有以下代码,我在while循环中的API_XXX.put(它调用utl_file.put)中调用了这些代码。l_xmldoc是getReportXML函数的CLOB,该函数返回xml CLOB 我编写的将xml写入文件的代码如下: l_offset := 1; WHILE (l_offset <= l_length) LOOP l_char := dbms_lob.substr(l_xmldoc,1,l_offset); IF (l_
utl_file.put
)中调用了这些代码。l_xmldoc是getReportXML函数的CLOB,该函数返回xml CLOB
我编写的将xml写入文件的代码如下:
l_offset := 1;
WHILE (l_offset <= l_length)
LOOP
l_char := dbms_lob.substr(l_xmldoc,1,l_offset);
IF (l_char = to_char(10)) ---I also tried if (l_char=chr(10)) but it did not work
THEN
API_XXXX.new_line(API_XXX.output, 1);
ELSE
API_XXXX.put(fnd_API_XXX.output, l_char);
END IF;
l_offset := l_offset + 1;
END LOOP;
API\u XXX.new\u line
类似于(line是要写入的行数):
我注意到,客户端的put/new_行过程有时会在客户的while循环中引发UTL_文件。由于未知原因(可能是因为l_长度太大(高达167465)),写入错误
我读
. 我发现这是同样的原因,我的l_xmldoc非常大,当我循环它时,我发现它没有一个新的行终止符,所以缓冲区高达32767,即使我每次都刷新
那么,我应该如何将l_xmldoc转换为带有新行终止符的varchar呢
PS:我确认我的客户正在使用Oralce 11g只是一个猜测,但是您可以尝试使用chr(10)来确定/编写换行符,而不是“to_char(10)”。不确定这是否能解决您的问题,但有时很长的行(没有换行符)可能会导致问题
例如:
declare
l_clob clob;
l_char char;
begin
l_clob := 'Line 1' || chr(10) || 'Line 2' || chr(10);
for i in 1 .. DBMS_LOB.GETLENGTH(l_clob)
loop
l_char := dbms_lob.substr(l_clob, 1, i);
if (l_char = chr(10)) then
--if (l_char = to_char(10)) then
dbms_output.put_line('Found a newline at position ' || i);
end if;
end loop;
end;
注意chr(10)和to_char(10)之间的区别。很容易测试这是否解决了您的问题
发布您正在使用的Oracle版本!或者我们可以随便猜
您的fflush
将无法按预期工作-从:
FFLUSH将挂起的数据物理写入由文件句柄标识的文件。通常,写入文件的数据是缓冲的。FFLUSH过程强制将缓冲数据写入文件数据必须以换行符结尾。
t一行是对的,到_CHAR(10)的那行是错的!只需尝试从DUAL中选择字符(10)
您将得到10
,然后将其与单个字符进行比较。单个字符永远不会是“10”,因为10有两个字符
- Quick&Dirty:由于您似乎并不关心性能,因此只需每隔X字节关闭一个文件,然后使用for append重新打开它。因此,只需添加到循环中:
IF MOD( l_offset, 32000 ) = 0 THEN UTL_FILE.FCLOSE( f_out ); UTL_FILE.FOPEN( out_fpath, out_fname, f_out, 'a', 32767 ); END IF;
- 为正确的作业使用正确的工具:
不适合处理复杂数据。UTL_文件的唯一用例是以换行符分隔的小文本行。对于其他所有内容,您应该写入原始字节!(这也将允许您对编码进行porper控制,目前这只是小型vanilly幸运猜测)UTL\u文件
- 使用NIO FileChannel编写Java存储过程-快速、安全、美观。。。但是要小心,你的程序可能会运行快10倍
UTL\u文件。将\u raw
放入以写入我的文件。一般来说,我先将clob转换为blob,然后再将其写入文件。@user272735,您是否遇到过我的问题?你知道为什么吗?你确定你的解决方案有效吗?请在回答中分享你的代码。我还没有测试过这个问题,但我怀疑在调用UTL_FILE.PUT或PUT_LINE时,输入长度不能超过PL/SQL(32767)中VARCHAR2允许的最大值。你能分享一个代码示例吗?另外,我的api在每次输入一个字符后都会调用fflush。所以我们现在没有写一行,我看到有人对这个答案投了更高的票,你的意思是我把字符(10)替换成chr(10)会有帮助吗?有什么区别?请你解释一下好吗?to_CHAR(10)将10(数字)转换为10(字符)。CHR(10)将十进制转换为字符,在本例中为新行符号。CHR(10)是一个换行符。它与to_char(10)不同,后者将数字10转换为字符串“10”。因此,您的代码永远不会找到新行,也永远不会编写新行(调用utl_file.newline的API代码永远不会被调用)。我相信,这部电影需要新线终结者。修复代码并进行测试非常简单。@t谢谢!因为我无法轻松测试这个问题,所以我将等待客户的反馈。我对你的回答感到惊讶,因为这已经有效多年了……但我仍然会尝试。那么,如果FFLUSH工作正常,如果我只放一个短的varchar,而不放一个新的行终止符?虽然我同意,但你的解决方案对我来说并不适用。1.我不知道打开了哪个文件,因为我的api为这个文件创建了一个随机名称并为我打开了它,所以我无法重新打开该文件。2.我不能把_raw放进去,因为API没有给我这个(同样,我必须使用API来打开文件)。3.Java过程不是选择,我必须在plsql中写入。“通常,写入文件的数据是缓冲的。FFLUSH过程强制将缓冲的数据写入文件。数据必须以换行符终止。”此外,Oracle文档中的这句话让我很困惑。它说,当我刷新时,它会强制将数据写入文件。但是我对每一个字符都进行了填充,并且这个字符没有新的行终止符。为什么在过去的几十年里不存在任何问题?@Jaskey请理解这句话:如果没有换行符,FFLUSH什么都做不了当且仅当存在换行符终止符时,fflush将刷新缓冲区中的所有内容,直到并包括此换行符使用Short varchar不会有问题,因为FCLOSE最终会刷新所有内容!但是,对于长文本,缓冲区将
declare
l_clob clob;
l_char char;
begin
l_clob := 'Line 1' || chr(10) || 'Line 2' || chr(10);
for i in 1 .. DBMS_LOB.GETLENGTH(l_clob)
loop
l_char := dbms_lob.substr(l_clob, 1, i);
if (l_char = chr(10)) then
--if (l_char = to_char(10)) then
dbms_output.put_line('Found a newline at position ' || i);
end if;
end loop;
end;
IF MOD( l_offset, 32000 ) = 0
THEN
UTL_FILE.FCLOSE( f_out );
UTL_FILE.FOPEN( out_fpath, out_fname, f_out, 'a', 32767 );
END IF;