Is there any way to flush output from PL/SQL in Oracle?

后端 未结 6 1083
情深已故
情深已故 2020-11-29 06:02

I have an SQL script that is called from within a shell script and takes a long time to run. It currently contains dbms_output.put_line statements at various po

6条回答
  •  执念已碎
    2020-11-29 06:53

    If it is possible to you, you should replace the calls to dbms_output.put_line by your own function.

    Here is the code for this function WRITE_LOG -- if you want to have the ability to choose between 2 logging solutions:

    write logs to a table in an autonomous transaction

    CREATE OR REPLACE PROCEDURE to_dbg_table(p_log varchar2)
      -- table mode: 
      -- requires
      -- CREATE TABLE dbg (u varchar2(200)   --- username
      --                 , d timestamp       --- date
      --                 , l varchar2(4000)  --- log 
      -- );
    AS
       pragma autonomous_transaction;
    BEGIN
      insert into dbg(u, d, l) values (user, sysdate, p_log);
      commit;
    END to_dbg_table;
    /
    

    or write directly to the DB server that hosts your database

    This uses the Oracle directory TMP_DIR

    CREATE OR REPLACE PROCEDURE to_dbg_file(p_fname varchar2, p_log varchar2)
      -- file mode: 
      -- requires
    --- 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', p_fname, 'A');
      utl_file.put_line(l_file, p_log);
      utl_file.fflush(l_file);
      utl_file.fclose(l_file);
    END to_dbg_file;
    /
    


    WRITE_LOG

    Then the WRITE_LOG procedure which can switch between the 2 uses, or be deactivated to avoid performances loss (g_DEBUG:=FALSE).

    CREATE OR REPLACE PROCEDURE write_log(p_log varchar2) AS
      -- g_DEBUG can be set as a package variable defaulted to FALSE
      -- then change it when debugging is required
      g_DEBUG boolean := true;
      -- the log file name can be set with several methods...
      g_logfname varchar2(32767) := 'my_output.log';
      -- choose between 2 logging solutions:
      -- file mode: 
      g_TYPE varchar2(7):= 'file';
      -- table mode: 
      --g_TYPE varchar2(7):= 'table';
      -----------------------------------------------------------------
    BEGIN
      if g_DEBUG then
        if g_TYPE='file' then
          to_dbg_file(g_logfname, p_log);
        elsif g_TYPE='table' then
          to_dbg_table(p_log);
        end if;
      end if;  
    END write_log;
    /
    

    And here is how to test the above:

    1) Launch this (file mode) from your SQLPLUS:

    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) on the database server, open a shell and

        tail -f -n500 /directory/where/oracle/can/write/on/DB_server/my_output.log
    

提交回复
热议问题