如何显示存储过程的输出?

时间:2012-10-30 08:58:23

标签: oracle stored-procedures plsql feedback output

我正在处理数百万行,这需要几个小时,所以我想要一些反馈,让我了解一下这个过程的状态。由于输出仅在完成执行后才可用,因此无法从存储过程获得实时反馈。任何解决方案?

3 个答案:

答案 0 :(得分:4)

有几种解决方案。

一种是写入某些描述的日志。您可以使用文件(writing out with UTL_FILE)或表格(使用autonomous transactions,以便在不影响主要交易的情况下在另一个会话中显示记录。)

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

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

答案 1 :(得分: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;
/

答案 2 :(得分:2)

从运行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进行测试。