Plsql 保存点和提交之间的冲突

Plsql 保存点和提交之间的冲突,plsql,oracle11g,Plsql,Oracle11g,我有一个需要一些时间才能完成的代码块,并且我在一个表上创建了一个进度变量,该进程将对其进行更新,以便最终用户可以知道还有多少需要完成 问题是,代码块被视为一个原子事务,因此进度变量值将仅显示0%或100%,除非我使用commit语句,该语句将删除在块上的上一点声明的保存点,并且如果发生异常,它将不会被识别为有效 代码如下所示: begin /*do some stuff*/ savepoint p_savepoint; for q in (somequery) loop

我有一个需要一些时间才能完成的代码块,并且我在一个表上创建了一个进度变量,该进程将对其进行更新,以便最终用户可以知道还有多少需要完成

问题是,代码块被视为一个原子事务,因此进度变量值将仅显示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;

有什么办法可以解决这个问题吗?

听起来您想在自主事务中更新进度。这是使用自治事务有意义的极少数情况之一

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;

听起来您想在自主事务中更新进度。这是使用自治事务有意义的极少数情况之一

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;

如果你只想展示你的循环的进展,你可能想考虑使用<代码> dBMSUpApdioTysIngIs<代码>,这样你就可以把这些信息放进 V$SeStuxLoops,参见这里:@我明天会尝试。如果你只想展示你的循环的进展,你可能想考虑使用<代码> DbMSyAppultIsIOFION/CODE >,而不是让你把这些信息放进 V$SeStuxLoops,参见这里:@ AyHORSESY,谢谢你,我明天再试试。