Отладка нашего собственного кода достаточно сложна, удаленная отладка чужого кода практически невозможна. Что мы можем сделать, так это предоставить вам некоторые рекомендации, которые помогут отладить ваш код.
По сути, один и тот же код ведет себя по-разному, когда вызывается из разных клиентов с одинаковыми параметрами. Наиболее вероятное объяснение состоит в том, что вызов VBA не передает значения параметров, которые, по вашему мнению, являются (возможно, существует неправильно названная ячейка или неявное преобразование типа данных), но единственный способ узнать - встроить некоторую трассировку в ваш код. Это означает просто написание отладочных сообщений из внутреннего кода.
К сожалению, распространенным способом сделать это является использование DBMS_OUTPUT, AKA The Devil's Debugger. Это записывает на экран, что исключает его для вашего сценария, потому что вы хотите вызвать процедуру из VBA. Таким образом, вы можете записать в файл, используя UTL_FILE или LOG_TABLE. Использование таблицы журналов, вероятно, в большей степени снижает производительность, чем запись в файл ОС, но с ней легче работать (по крайней мере, если вы более счастливы с SQL, чем sed
и grep
).
Необработанная реализация трассировки будет выглядеть примерно так. Использование AUTONOMOUS_TRANSACTION является необязательным, но оно гарантирует записи трассировки в случае, если основная процедура вызывает исключение; это также позволяет вам контролировать выход в режиме реального времени.
create or replace procedure your_proc
(p1 in number
, p2 in varchar2
...
, p38 in date)
is
....
procedure write_log
(p_action in varchar2
, p_add_text in varchar2 := null)
is
pragma autonomous_transaction;
begin
insert into log_table
(id, ts, action, add_text)
values
(log_seqno.nextval, systimestamp, p_action, p_add_text);
commit;
end write_log ;
begin
write_log ('YOUR_PROC::START', user);
write_log ('YOUR_PROC::PARAM', 'P1='||to_char(p1));
write_log ('YOUR_PROC::PARAM', 'P2='||p2);
....
write_log ('YOUR_PROC::PARAM', 'P32='||to_char(p32));
...
-- main body of procedure happens here
...
write_log ('YOUR_PROC::END');
exception
when some_exception then
write_log ('YOUR_PROC::EXCEPTION='||some_exception);
raise;
end your_proc;
Помимо записи значений параметров, вы захотите записать этапы в потоке программы, особенно отмечая циклы и условия; переключатель (ЕСЛИ ... ДАЛЕЕ, СЛУЧАЙ и т. д.).
Запустите программу дважды, один раз из VBA, один раз из SQL * Plus. Затем сравните два набора выходных данных. Там, где они различаются, вы ответите.