【问题标题】:How to display output from stored procedure?如何显示存储过程的输出?
【发布时间】:2012-10-30 08:58:22
【问题描述】:

我正在处理数百万行,这需要几个小时,所以我想要一些反馈来让我了解流程的状态。不可能从存储过程中获得实时反馈,因为只有在完成执行后才能获得输出。有什么解决办法吗?

【问题讨论】:

    标签: oracle stored-procedures plsql feedback output


    【解决方案1】:

    有几个解决方案。

    一种是写入一些描述的日志。您可以使用文件 (writing out with UTL_FILE) 或表(使用 autonomous transactions 以便记录在另一个会话中可见,而不会影响主事务)。

    另一种解决方案是使用 DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS 写入 V$SESSION_LONGOPS 视图。 Find out more

    我认为记录长时间运行的后台程序总是一个好主意。如果出现问题,您的日志是您拥有的唯一信息来源。

    【讨论】:

      【解决方案2】:

      您可以有一个写入不同表的 ReportStatus 过程(您可以在过程运行时从中选择一个)。

      它需要一个 PRAGMA AUTONOMOUS_TRANSACTION 以便它可以独立于您的主程序提交。

      例子:

      CREATE OR REPLACE PROCEDURE ReportStatus(status NUMBER)
      AS
        PRAGMA AUTONOMOUS_TRANSACTION;
      BEGIN
        INSERT INTO StatusTable VALUES(SYSDATE, status);
        COMMIT;
      END ReportStatus;
      /
      

      【讨论】:

        【解决方案3】:

        从运行的 PL/SQL 块中获取反馈的另一种方法是使用会话间通信。要使用此解决方案,您至少需要两个会话。

        在审计(第一次)会话中:

        set head off arrays 1 pages 0 feedback off timing off
        select column_value notification from table (notificationReceive);
        

        在第一条消息到达之前,它会一直卡在那里。
        作为下一步,在另一个(第二个)会话中执行您的 PL/SQL 块:

        begin 
            notificationSend ('START: '||'myBlockName');
            /* UPDATE table1 SET col1 = value ... WHERE some condition;
            */ dbms_lock.sleep(3);
            notificationSend ('Updated 1000000 rows'); -- sql%rowcount instead of literal 
            /* INSERT INTO table2 (val1, SYSDATE, v_user_id);
            */ dbms_lock.sleep(2);
            notificationSend ('Inserted 1000000 rows'); 
            notificationSend ('ENDTX');
        end;
        /
        

        现在,您可以回到第一个会话并查看运行 PL/SQL 块的实时反馈:

        11:13:39: START: myBlockName
        
        11:13:42: Updated 1000000 rows
        
        11:13:44: Inserted 1000000 rows
        

        下面几乎一行函数的代码:

        create or replace procedure notificationSend (message varchar2) is
        pragma autonomous_transaction;
        begin
            dbms_alert.signal ('feedback$_queue', message);
            commit;
        end;
        /
        create or replace function notificationReceive return sys.odciVarchar2List pipelined is
        pragma autonomous_transaction;
            message varchar2(1800) := 'NONE';
            status number := -1;
        begin 
            dbms_alert.register('feedback$_queue');
            <<reading>> loop 
                dbms_alert.waitone('feedback$_queue', message, status); 
                if status = 0 and message != 'ENDTX' then
                    pipe row (to_char (sysdate, 'hh:mi:ss')||': '||message);
                    pipe row (null); -- dummy row for prefetch in sqlplus 
                else 
                    exit reading; 
                end if;
            end loop reading;
            dbms_alert.remove('feedback$_queue');
            return;
        end;
        /
        

        使用版本 11.2.0.4.0、12.2.0.1.0 测试。

        【讨论】:

          猜你喜欢
          • 2013-01-12
          • 1970-01-01
          • 1970-01-01
          • 2015-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多