后台处理程序未将 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...'); 以检查您的块是否实际正在执行 - 也许其中一个查询没有返回任何记录,这可以解释为什么没有生成输出。 将其重写为单个查询并假脱机结果。完全不需要循环模拟连接的结果集。此外,preformatmarkup 命令的一个选项。你不要单独使用它,当你这样做时肯定会收到“未知的设置选项”错误。 【参考方案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++) 记录,记录器未将日志写入文件

批处理文件未将文件内容分配给变量

Debug.WriteLine 未将输出写入 Visual Studio 2010 中的 OutputWindows

C#写入文件内容时提示:文件正被另一个人或程序使用

提示 未将对象引用设置到对象的实例 怎么处理?