2016-11-07 101 views
0

我有一段代码块需要一些时间才能完成,并且我在表上创建了一个进度变量,进程将更新,以便最终用户可以知道剩下多少要完成。保存点和提交之间的冲突

问题在于代码块被视为原子事务,因此进度变量值将只显示0%或100%,除非我使用commit语句,该语句将删除在上一个点上声明的保存点块,如果发生异常,它不会被识别为有效。

的代码是这样的:

begin 
    /*do some stuff*/ 
    savepoint p_savepoint; 
    for q in (somequery) loop /*Really long loop*/ 
      /*Do some other stuff*/ 
      update t_sys_state set p1_progress = percentage 
      where user_id = 'theuserid'; 
      commit; /*This commit make the real progress value available*/ 
    end loop; 
    exception 
      when others then 
        rollback to p_savepoint; /*This savepoint is not recognized because of the previous commit*/ 
        raise; 
end; 

有没有解决这个办法吗?

+4

如果你只是想显示你的循环的进度,你可能要考虑使用'dbms_application_info'代替,它可以让你把信息转化为'V $ session_longops',看例如这里:http://stackoverflow.com/a/40154203/330315 –

+0

@a_horse_with_no_name谢谢,明天我会试试。 – Typo

回答

3

这听起来像你想更新自动交易中的进度。这是使用自主交易很有意义的极少数情况之一。

CREATE OR REPLACE PROCEDURE log_progress(p_user IN varchar2, 
              p_percentage IN number) 
AS 
    PRAGMA autonomous_transaction; 
BEGIN 
    UPDATE t_sys_state 
    SET p1_progress = p_percentage 
    WHERE user_id  = p_user; 
    commit; 
END; 

然后

begin 
    /*do some stuff*/ 
    savepoint p_savepoint; 
    for q in (somequery) loop /*Really long loop*/ 
      /*Do some other stuff*/ 
      log_progress('theuserid', percentage); 
    end loop; 
    exception 
      when others then 
        rollback to p_savepoint; /*This savepoint is not recognized because of the previous commit*/ 
        raise; 
end; 
+0

不错,我明天会试一试,谢谢。 – Typo