#stored-procedures #plsql #oracle10g #oracle-sqldeveloper #stored-functions
#хранимые процедуры #plsql #oracle10g #oracle-sqldeveloper #сохраненные функции #хранимые функции
Вопрос:
У меня есть процедура для обновления баланса с даты начала до даты окончания, а также я хочу отслеживать количество вставляемых записей. Я использую dbms_output.put_line, чтобы получить количество вставленных записей, но это не дает никаких выходных данных, когда выполнение завершается, выводится результат подсчета. Код процедуры выглядит следующим образом :
create or replace function updatebal(start_date IN DATE, end_date IN DATE)
RETURN NUMBER
IS
difference number;
curr_r number;
BEGIN
difference := end_date - start_date;
curr_r := 0;
while curr_r <= difference LOOP
curr_r := curr_r 10;
for curr_in in 1..10 LOOP
date_value := date_value 1 ;
insertAvailBal(date_value);
commit;
select count(*) into totalCount from avail_bal;
dbms_output.put_line('total count' || totalCount);
end loop;
END LOOP;
RETURN 1;
END;
Теперь я пытаюсь вывести итоговое значение из этой процедуры, чтобы получить количество строк, вставленных в эту таблицу avail_bal. Но не получаем выходных данных.
Пожалуйста, помогите мне, заранее спасибо
Ответ №1:
Как Тони уже ответил: вы не можете изменить поведение dbms_output.
Рекомендуемый способ передачи сигналов о ходе выполнения за пределы хранимой процедуры — использовать dbms_application_info
пакет для управления информацией в v$session_longops
Вы даже можете управлять отдельными индикаторами выполнения для внешнего и внутреннего цикла. v$session_longops
будет даже отображаться оценка того, сколько времени займет процесс, на основе средней продолжительности с течением времени. Эти оценки довольно точны, если время выполнения для каждого (сообщаемого) шага является достаточно постоянным.
Вы можете улучшить свою функцию следующим образом:
create or replace function updatebal(start_date IN DATE, end_date IN DATE)
RETURN NUMBER
IS
difference number;
curr_r number;
main_index binary_integer;
sub_index binary_integer;
main_slno binary_integer;
sub_slno binary_integer;
BEGIN
difference := end_date - start_date;
curr_r := 0;
-- initialize the module information
dbms_application_info.set_module('updatebal', 'Calculate Balance');
-- initialize two different "handles" for the inner and outer loop
main_index := dbms_application_info.set_session_longops_nohint;
sub_index := dbms_application_info.set_session_longops_nohint;
while curr_r <= difference LOOP
curr_r := curr_r 10;
-- report each outer step
dbms_application_info.set_session_longops(rindex => main_index,
slno => main_slno,
op_name => 'main loop',
sofar => curr_r,
totalwork => difference);
for curr_in in 1..10 LOOP
date_value := date_value 1;
insertAvailBal(date_value);
commit;
select count(*) into totalCount from avail_bal;
-- report each inner step with the totalcount
dbms_application_info.set_session_longops(
rindex => sub_index,
slno => sub_slno,
op_name => 'Sub Loop, totalcount'||totalcount,
sofar => curr_in, totalwork => 10);
end loop;
END LOOP;
RETURN 1;
dbms_application_info.set_module(null,null);
END;
/
Смотрите руководство для получения более подробной информации:
https://docs.oracle.com/database/121/ARPLS/d_appinf.htm#ARPLS003
Ответ №2:
Вот как работает dbms_output, он отображает все свои выходные данные после завершения запуска, вы не можете отслеживать это в режиме реального времени.
Если вам действительно нужен этот мониторинг прогресса в режиме реального времени, вы могли бы использовать процедуру с автономной транзакцией для вставки сообщений в специальную таблицу, а затем из другого сеанса вы могли бы просматривать содержимое этой таблицы, пока процесс все еще выполняется.
Пример такой процедуры:
procedure log_message (p_message varchar2) is
pragma autonomous_transaction;
begin
insert into message_table (message) values (p_message);
commit;
end;