2009-11-13 145 views
19

我有一些可能需要几分钟才能运行的pl/sql程序。在开发它们时,我添加了一些打印语句来帮助调试,并提供一些反馈和进度指示器。最初,我在小型测试台上运行这些测试,输出几乎是瞬间的。现在我正在测试运行几分钟的大型测试集,我发现打印到控制台不再合适,因为在程序结束之前没有任何东西被打印。我习惯于在不缓冲输出并立即打印的环境中工作,并且添加简单的打印语句以进行简单的调试和诊断是很常见的。Oracle PL/SQL - 即时输出/控制台打印提示

是否有可能在pl/sql中立即打印输出(未缓冲)?如果不是,人们推荐什么替代方案来获得类似的结果?

回答

17

你可以拥有,使用一个自治事务类似消息写入表的程序:

procedure log (p_message) 
is 
    pragma autonomous_transaction; 
begin 
    insert into message_log (user, datetime, message) 
    values (user, sysdate, p_message); 
    commit; 
end; 

然后从另一个Oracle会话监控表。

+1

关于pragma autonomous_transaction的更多信息http://stackoverflow.com/questions/1335331/autonomoustransaction – caddis 2009-11-13 17:57:32

+1

这看起来不错,我今天可能会试试:) 它与使用管道的其他建议相比如何?哪个更容易查看和监控? – FrustratedWithFormsDesigner 2009-11-16 16:42:08

+0

我还没有使用管道方法,所以不能对此发表评论。表格方法的一个不同是消息是持久的。这可能是一个优点,但它也意味着你必须管理它们,以便表格不会无限增长! – 2009-11-16 16:51:05

8

我们对此有个小窍门。

你可以使用DBMS_APPLICATION_INFO.set_client_info(“某些信息在这里”); 创建一些变量并替换“”中的字符串。

并使用从v $ session中选择client_info来监视进度。

+0

我有权访问v $ session_longops和v $ session_connect_info,它们都没有client_info字段。 v $ session_longops会一样好吗? – FrustratedWithFormsDesigner 2009-11-13 16:02:39

+1

不,您需要使用v $会话视图。如果您无法访问,请问DBA。 – 2009-11-13 16:37:12

1

通常有两种选择:

  • 将输出发送到Oracle表 (或临时表)
  • 写的(数据库主机)文件系统与UTL_FILE

如果您没有操作系统访问数据库主机的权限,您仍然可以写入dbhost文件系统并将Oracle外部定义的表绑定到该文件,以便可以使用SELECT查询该文件。

1

它可能取决于您的客户端工具。我暂时还没有使用SQL * Plus,但是当我在PL/SQL Developer中调试过程时,我打开一个命令窗口并发出一个SET SERVEROUTPUT ON命令。然后当我执行程序时,任何由DBMS_OUTPUT.PUT_LINE打印的东西都会立即显示出来。

编辑:你是对的,我想我只是看到与大量的输出或东西。无论如何,我做了一些在线搜索,碰到这个log4plsql - 可能会有用。

+0

我是PL/SQL Developer的用户,不起作用。脚本执行完毕后,所有输出都会立即打印出来。 – FrustratedWithFormsDesigner 2009-11-13 15:55:30

1

另一种方法是使用返回日志信息的流水线函数。请参阅此处的示例:http://berxblog.blogspot.com/2009/01/pipelined-function-vs-dbmsoutput.html当您使用流水线功能时,不必使用其他SQLPLUS/Toad/sql开发人员等...会话。

+0

这很有趣,但是我不必将现有的函数修改为流水线,或者可能将它包装在流水线函数中? – FrustratedWithFormsDesigner 2009-11-16 16:25:45

+0

当然,你必须改变你的代码。只是将它封装在流水线函数中并不能帮助您,因为您希望立即进行日志记录,而不仅仅是在完成某些事情时进行日志记录。 – tuinstoel 2009-11-16 18:42:35

2

我一直在使用dbms_pipe来达到这个目的。将消息发送到命名管道,并从另一个会话读取它们。当写入和读取过程可能连接到不同的节点时,此方法可能无法在RAC环境中使用。

或者,您可以使用使用“pragma autonomous_transaction”在自己的会话中运行的过程将消息插入到表中。您可以从另一个会话查询这些消息

编辑:我看到我的第二个选项已被提及。

+0

这两个看起来都像是有趣的可能性,尽管当我尝试使用dbms_pipe包时,出现错误(可能与权限相关)。 每种方法的优缺点是什么?我对Oracle管道了解不多,所以我不知道如何评估,但它比表驱动解决方案更接近我想要的。 – FrustratedWithFormsDesigner 2009-11-16 16:48:10

1

您可以在PL/SQL Developer中使用DBMS管道和管道查看器异步捕获放入管道中的所有信息。

小心只有在有人阅读时才将东西放入管道中。否则,当管道已满时,您的呼叫将失败。

还有使用事件的可能性,PL/SQL Developer还有一个事件监视器。文档应该提供一个如何去做的例子。

+0

这看起来不错,但我得到一个错误:“标识符”DBMS_PIPE'必须声明“,我想我需要与DBA谈谈此事。可能是权限问题。 – FrustratedWithFormsDesigner 2009-11-16 16:37:42

0

另一个选择是让你的PL/SQL调用一个过程来发送一封包含日志消息的电子邮件。这要求您的数据库具有电子邮件发送功能,可以使用UTL_SMTP添加电子邮件发送功能。