后台处理程序未将 dbms_output 写入文件
Posted
技术标签:
【中文标题】后台处理程序未将 dbms_output 写入文件【英文标题】:Spooler not writing dbms_output to file 【发布时间】:2014-02-25 22:39:38 【问题描述】:我需要将循环的输出假脱机到文件中。我的代码如下:
set termout off
set echo off
set colsep ''
set linesize 5000
set heading off
set feedback off
set preformat off
set trimspool on
set serverout on
spool 'C:\folder\script.sql'
begin
for rec in (select unique prgm_id from tmp_table_output) loop
for rec2 in (select unique cmpg_id from tmp_table_output where prgm_id = rec.prgm_id) loop
dbms_output.put_line('spool ''C:\folder\PRG''||lpad('||rec.prgm_id||', 4, 0)||''_CMPG''||lpad('||rec2.cmpg_id||', 4, 0)||''.txt'' CREATE');
dbms_output.put_line('SELECT field FROM tmp_table_output where prgm_id = '||rec.prgm_id||' and cmpg_id = '||rec2.cmpg_id);
dbms_output.put_line('spool off');
end loop;
end loop;
end;
/
spool off;
但是,当我检查 script.sql 文件时,并没有实际迭代循环,而是输出:
begin
for rec in (select unique prgm_id from tmp_table_output) loop
for rec2 in (select unique cmpg_id from tmp_table_output where prgm_id = rec.prgm_id) loop
dbms_output.put_line('spool ''C:\RemoteOnboarding\PRG''||lpad('||rec.prgm_id||', 4, 0)||''_CMPG''||lpad('||rec2.cmpg_id||', 4, 0)||''.txt'' CREATE');
dbms_output.put_line('SELECT field FROM tmp_unica_output where prgm_id = '||rec.prgm_id||' and cmpg_id = '||rec2.cmpg_id);
dbms_output.put_line('spool off');
end loop;
end loop;
end;
/
spool off;
如何让它将循环输出写入文件?
【问题讨论】:
我会检查/
是否在该行的第一列(即前面没有空格);另外,在begin
之后立即放置一个dbms_output.put_line('prompt starting...');
以检查您的块是否实际正在执行 - 也许其中一个查询没有返回任何记录,这可以解释为什么没有生成输出。
将其重写为单个查询并假脱机结果。完全不需要循环模拟连接的结果集。此外,preformat
是markup
命令的一个选项。你不要单独使用它,当你这样做时肯定会收到“未知的设置选项”错误。
【参考方案1】:
SPOOL
是一个 SQL*Plus 命令。如果要从 PL/SQL 写入文件,请使用 UTL_FILE
包。
【讨论】:
那么有没有办法让这段代码正常工作?我必须使用 UTL_FILE 包? 如果您使用的是 SPOOL,那么您得到的是 SQL*Plus 中发生的所有事情的记录。因此,您应该看到 DBMS_OUTPUT 的结果与代码本身混合在一起。如果您希望 PL/SQL 编写一个干净的文件,该文件只包含您从 PL/SQL 写入的内容,您应该使用 UTL_FILE。 实际上,我不确定这是否完全正确(我可能错了,所以我还没有投票)。UTL_FILE
仅在输出到服务器上的文件时才有用 - SPOOL 对于在客户端上获取文件很有用。 OP 确实有SPOOL 'C:\folder\script.sql'
,他有set serverout on
,所以我希望输出文件同时具有PL/SQL 块,然后/
应该执行该块。我以前写过这种风格的 SQLPlus 脚本,它可以工作——基本上它是用来生成一系列 SQLPlus 脚本的。
Jeffrey,你说得对,UTL_FILE 仅对写入服务器有用,而 spool 将写入客户端,而 SQLPlus 恰好在其中运行,我应该这样做那个区别。我想这对我来说并不是 100% 清楚,确切的目标是什么。此外,OP 所做的评论,关于他没有看到代码循环的输出,只有他在 SQL 中输入的代码Plus,似乎表明存在问题,我看到你已经在评论中指出了这一点问题。让我们看看 OP 怎么说,我要么编辑我的答案,要么删除它。
@JeffreyKemp 你在我想做的事情上是正确的。抱歉,如果不清楚。根据您的评论,我仍然无法看到我的问题是什么。【参考方案2】:
如果您可以将 BEGIN 和 END 块之间的代码更改为单个 SQL,它可能会对您有所帮助。
这里有一个例子,你可以怎么做,代码没有经过测试,因为我没有你所有的设置,也可能有一些语法错误,如果你遇到任何错误,请尝试让我知道
set termout off
set echo off
set colsep ''
set linesize 5000
set heading off
set feedback off
set preformat off
set trimspool on
set serverout on
spool 'C:\folder\script.sql'
select text from (
select unique 1 as rn, rec.prgm_id, rec2.cmpg_id, 'spool ''C:\folder\PRG''||lpad('||rec.prgm_id||', 4, 0)||''_CMPG''||lpad('||rec2.cmpg_id||', 4, 0)||''.txt'' CREATE' as text
from tmp_table_output rec, tmp_table_output rec2
where a.prgm_id = b.prgm_id
union all
select 2, rec.prgm_id, rec2.cmpg_id, 'SELECT field FROM tmp_table_output where prgm_id = '||rec.prgm_id||' and cmpg_id = '||rec2.cmpg_id
from tmp_table_output rec, tmp_table_output rec2
where a.prgm_id = b.prgm_id
union all
select unique 3, rec.prgm_id, rec2.cmpg_id, 'spool off'
from tmp_table_output rec, tmp_table_output rec2
where a.prgm_id = b.prgm_id
)
order by prgm_id, cmpg_id, rn;
spool off;
【讨论】:
尝试您的代码会得到与我相同的结果。它只是输出 pl/sql 你确定吗?我只使用 SQL,没有使用 PL/SQL。能否只在 SQL*PLUS 中运行 select 语句并检查输出是否正确?以上是关于后台处理程序未将 dbms_output 写入文件的主要内容,如果未能解决你的问题,请参考以下文章
Ionic 5 Native File 插件未将文件写入 dataDirectory
使用 spdlog (C++) 记录,记录器未将日志写入文件