如何将DBMS_OUTPUT.PUT_LINE的输出redirect到一个文件?
我需要在pl / sql中debugging数字的时间程序,我想用:
SELECT systimestamp FROM dual INTO time_db; DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
但我不明白输出到哪里,我如何将它redirect到一个日志文件,其中将包含我想收集的所有数据?
DBMS_OUTPUT
不是debugging的最佳工具,因为大多数环境本身并不使用它。 如果要捕获DBMS_OUTPUT
的输出,则只需使用DBMS_OUTPUT.get_line
过程。
这是一个小例子:
SQL> create directory tmp as '/tmp/'; Directory created SQL> CREATE OR REPLACE PROCEDURE write_log AS 2 l_line VARCHAR2(255); 3 l_done NUMBER; 4 l_file utl_file.file_type; 5 BEGIN 6 l_file := utl_file.fopen('TMP', 'foo.log', 'A'); 7 LOOP 8 EXIT WHEN l_done = 1; 9 dbms_output.get_line(l_line, l_done); 10 utl_file.put_line(l_file, l_line); 11 END LOOP; 12 utl_file.fflush(l_file); 13 utl_file.fclose(l_file); 14 END write_log; 15 / Procedure created SQL> BEGIN 2 dbms_output.enable(100000); 3 -- write something to DBMS_OUTPUT 4 dbms_output.put_line('this is a test'); 5 -- write the content of the buffer to a file 6 write_log; 7 END; 8 / PL/SQL procedure successfully completed SQL> host cat /tmp/foo.log this is a test
作为写入文件的替代方法,如何写入表格? 您可以调用您自己的DEBUG.OUTPUT过程,而不是调用DBMS_OUTPUT.PUT_LINE:
procedure output (p_text varchar2) is pragma autonomous_transaction; begin if g_debugging then insert into debug_messages (username, datetime, text) values (user, sysdate, p_text); commit; end if; end;
自治事务的使用允许您保留从回滚的事务(例如,在引发exception之后)产生的debugging消息,就像在使用文件时会发生的那样。
g_debugging布尔variables是一个包variables,当需要debugging输出时可以默认为false,并设置为true。
当然,你需要pipe理这张桌子,这样它才不会永远长大! 一种方法是每晚每周运行一次,并删除任何“旧”的debugging消息。
使用set serveroutput;
例如:
set serveroutput on; DECLARE x NUMBER; BEGIN x := 72600; dbms_output.put_line('The variable X = '); dbms_output.put_line(x); END;
如果你只是在SQL Plus中testing你的PL / SQL,你可以把它指向一个像这样的文件:
spool output.txt set serveroutput on begin SELECT systimestamp FROM dual INTO time_db; DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db); end; / spool off
像Toad和SQL Developer这样的IDE可以用其他方式捕获输出,但是我不太清楚。
除了Tony的回答之外,如果您正在寻找PL / SQL程序花在哪里的时间,那么还需要查看这部分Oracle PL / SQL文档。
使用UTL_FILE
而不是DBMS_OUTPUT
将输出redirect到一个文件:
请注意,所有这些输出都是在服务器端生成的。
使用DBMS_OUTPUT,文本在执行查询并存储在缓冲区时在服务器中生成。 然后在服务器完成查询数据检索时redirect到您的客户端应用程序。 也就是说,只有在查询结束时才能得到这个信息。
使用UTL_FILElogging的所有信息将被存储在服务器中的文件中。 当执行完成后,你将不得不导航到这个文件来获取信息。
希望这可以帮助。
它可能直接写入一个文件到承载你的数据库的数据库服务器,这将随着你的PL / SQL程序的执行而改变。
这使用Oracle目录 TMP_DIR
; 你必须声明它,并创build下面的过程:
CREATE OR REPLACE PROCEDURE write_log(p_log varchar2) -- file mode; thisrequires --- CREATE OR REPLACE DIRECTORY TMP_DIR as '/directory/where/oracle/can/write/on/DB_server/'; AS l_file utl_file.file_type; BEGIN l_file := utl_file.fopen('TMP_DIR', 'my_output.log', 'A'); utl_file.put_line(l_file, p_log); utl_file.fflush(l_file); utl_file.fclose(l_file); END write_log; /
以下是如何使用它:
1)从你的SQL * PLUS客户端启动它:
BEGIN write_log('this is a test'); for i in 1..100 loop DBMS_LOCK.sleep(1); write_log('iter=' || i); end loop; write_log('test complete'); END; /
2)在数据库服务器上,打开一个shell和
tail -f -n500 /directory/where/oracle/can/write/on/DB_server/my_output.log
一个古老的线程,但有另一种select。
自9i以来,您可以使用stream水线表格function。
首先,创build一个types为varchar的表格:
CREATE TYPE t_string_max IS TABLE OF VARCHAR2(32767);
其次,将代码包装在stream水线函数声明中:
CREATE FUNCTION fn_foo (bar VARCHAR2) -- your params RETURN t_string_max PIPELINED IS -- your vars BEGIN -- your code END; /
replacePIPE ROW
所有DBMS_OUTPUT.PUT_LINE
。
最后,这样称呼它:
SELECT * FROM TABLE(fn_foo('param'));
希望能帮助到你。
尝试这个:
SELECT systimestamp INTO time_db FROM dual ; DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);