views:

5728

answers:

6

Hi all.

I need to debug in pl/sql to figure times of procedures, I want to use:

SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);

but I don't understand where the output goes to and how can I redirect it to a log file that will contain all the data I want to collect?

I use Oracle db...

thanks!!! :)

+3  A: 

Using UTL_FILE instead of DBMS_OUTPUT will redirect output to a file:

http://oreilly.com/catalog/oraclebip/chapter/ch06.html

Rafa de Castro
thanks for the quick response :)I will try to give this a try (but it sounds really difficult to make it work), do you have any idea how to print the DBMS_OUTPUT to a file (it may be more easy)
+1  A: 

If you are just testing your PL/SQL in SQL Plus you can direct it to a file like this:

spool output.txt

begin
  SELECT systimestamp FROM dual INTO time_db;
  DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
end;
/

spool off

IDEs like Toad and SQL Developer can capture the output in other ways, but I'm not familiar with how.

Tony Andrews
thanks, but I'm testing a different application that uses the pl/sql db and I need the information to be saved to a file while the .sql script is not run from the sqldeveloper, any ideas?
Well, you can obtain the output produced by DBMS_OUTPUT in the calling application by calling DBMS_OUTPUT.ENABLE before writing any messages, and then calling DBMS_OUTPUT.GET_LINE or GET_LINES. But to then put that information into a file would require doing your own file opening/writing/closing, e.g. using UTL_FILE - in which case you may as well use UTL_FILE in the first place!
Tony Andrews
+1  A: 

As a side note, remember that all this output is generated in the server side.

Using DBMS_OUTPUT, the text is generated in the server while it executes your query and stored in a buffer. It is then redirected to your client app when the server finishes the query data retrieval. That is, you only get this info when the query ends.

With UTL_FILE all the information logged will be stored in a file in the server. When the execution finishes you will have to navigate to this file to get the information.

Hope this helps.

Juan Calero
+4  A: 

Hi aye,

DBMS_OUTPUT is not the best tool to debug, since most environments don't use it natively. If you want to capture the output of DBMS_OUTPUT however, you would simply use the DBMS_OUTPUT.get_line procedure.

Here is a small example:

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
Vincent Malgrat
+1 for mentioning the get_line procedure and the nice example.
Rob van Wijk
+1  A: 

As an alternative to writing to a file, how about writing to a table? Instead of calling DBMS_OUTPUT.PUT_LINE you could call your own DEBUG.OUTPUT procedure something like:

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;

The use of an autonomous transaction allows you to retain debug messages produced from transactions that get rolled back (e.g. after an exception is raised), as would happen if you were using a file.

The g_debugging boolean variable is a package variable that can be defaulted to false and set to true when debug output is required.

Of course, you need to manage that table so that it doesn't grow forever! One way would be a job that runs nightly/weekly and deletes any debug messages that are "old".

Tony Andrews
+1 For saying just what I was just typing!
carpenteri
+1  A: 

In addition to Tony's answer, if you are looking to find out where your PL/SQL program is spending it's time, it is also worth checking out this part of the Oracle PL/SQL documentation.

carpenteri
+1 for DBMS_PROFILER. It's always better to use an Oracle built-in whenever possible.
APC