在使用PL/SQL实现批量数据处理时,通常使用DBMS_OUTPUT.put_line('step a')实现;但由于该函数并不能实时输出(在整个PL/SQL代码执行结束后才输出),无法实现进度监控的效果。
这里摘录杨廷琨在《OracleDBA手记3》上的方法:
1,使用自治事务将进度插入日志表,通过查询日志表获取进度
create or replace procedure p_log(p_str in varchar2) as
pragma autonomous_transaction;
begin
insert into log values(sysdate,p_str);
commit;
end;
/
2,使用dbms_application_info.set_action('step a')实现,通过查询v$session.action获取进度
begin
dbms_application_info.set_action('step a');
end;
/
3,使用dbms_application_info.set_session_longops()实现,通过查询v$session_longops获取进度
set serveroutput on;
DECLARE
--异常
array_dml_errors EXCEPTION;
PRAGMA EXCEPTION_INIT(array_dml_errors, -24381);
--v$session_longops
l_rindex BINARY_INTEGER;
l_slno BINARY_INTEGER;
--error
l_errors NUMBER;
l_index NUMBER;
BEGIN
dbms_output.enable(NULL);
dbms_output.put_line('---Begin update users_chnl.sec_id');
l_rindex := dbms_application_info.set_session_longops_nohint;
dbms_application_info.set_session_longops(rindex => l_rindex,
slno => l_slno,
op_name => 'update table_a',
sofar => l_batch *
con_row_limit);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(dbms_utility.format_error_stack);
CLOSE cur;
END;
/
4,使用dbms_pipe.send_message发送进度信息,通过dbms_pipe.receive_message读取进度
--监控进程
declare
v_return number;
v_str varchar2(32767);
begin
v_return := dbms_pipe.create_pipe('p_test');
while(v_return = 0) loop
v_return := dbms_pipe.receive_message('p_test',1);
if v_return = 0 then
dbms_pipe.unpack_message(v_str);
p_log(v_str); --自治事务
end if;
end loop;
v_return := dbms_pipe.remove_pipe('p_test');
end;
/
--批量操作
declare
v_str varchar2(4000) := 'STEP BEGIN';
v_return number;
begin
dbms_pipe.pack_message(v_str);
v_return := dbms_pipe.send_message('p_test');
dbms_lock.sleep(60);
v_return := dbms_pipe.send_message('p_test');
dbms_lock.sleep(60);
v_return := dbms_pipe.send_message('p_test');
end;
/
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/18922393/viewspace-709035/ ,如需转载,请注明出处,否则将追究法律责任。