Как я могу устранить проблему с Oracle DBMS_SCHEDULER.CREATE_JOB? - PullRequest
0 голосов
/ 04 апреля 2019

Я пытаюсь выполнить процедуру внешней команды из Oracle. То, что я имею до сих пор, это;

Процедура Oracle;

CREATE OR REPLACE PROCEDURE DO_HOST_COMMAND 
(
  HOST_COMMAND IN VARCHAR2 
, ARGUMENT_LIST IN VARCHAR2 
, ARGUMENT_COUNT IN NUMBER 
, DELIMITER IN VARCHAR2 
) AS 
  JOB_ID VARCHAR2(100) := 'myjob_'||TO_CHAR(SYSTIMESTAMP,'YYYYMMDDHH24MISSFF6');
  CURRENT_ARGUMENT_COUNT NUMBER;
  CURRENT_ARGUMENT VARCHAR2(32767);
BEGIN

  DBMS_SCHEDULER.CREATE_JOB (JOB_NAME    => JOB_ID,
                              JOB_TYPE    => 'executable',
                              JOB_ACTION  => 'c:\windows\system32\cmd.exe',
                              NUMBER_OF_ARGUMENTS => ARGUMENT_COUNT + 1,
                              AUTO_DROP   => TRUE);
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (JOB_ID, 1, HOST_COMMAND);
  FOR CURRENT_ARGUMENT_COUNT IN 1..ARGUMENT_COUNT
  LOOP
    CURRENT_ARGUMENT := GET_DELIMITED_ELEMENT(ARGUMENT_LIST,DELIMITER,CURRENT_ARGUMENT_COUNT);
    DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (JOB_ID, CURRENT_ARGUMENT_COUNT + 1, CURRENT_ARGUMENT);
  END LOOP;
  DBMS_SCHEDULER.RUN_JOB (JOB_ID);

END DO_HOST_COMMAND;

Процедура команды Windows;

c:
cd \Temp
echo in test.cmd > test.log
copy %1  %2

Команда SQL для запуска этого;

exec do_host_command('c:\temp\test.cmd','test1.txt|test2.txt',2,'|');

Результат:

PL/SQL procedure successfully completed.

Однако ничего не происходит. Когда я бегу;

select * from user_scheduler_job_run_details where trunc(log_date) = trunc(sysdate);

Там написано, что работа выполнена успешно. Я посмотрел в журнале оповещений и файлах трассировки и ничего не могу найти. Я изменил права доступа к папке c: \ temp для всех пользователей с полным доступом.

Не уверен, где искать проблему. Какие дополнительные способы устранения неполадок мне следует сделать?

EDIT:

Это работает в Oracle 12c R2 в Windows 2016.

1 Ответ

2 голосов
/ 04 апреля 2019

Проблема в том, что вы неправильно набираете cmd.exe.Вам нужно передать /C ключ cmd.exe перед именем скрипта.Другими словами, вам нужно заставить базу данных выполнить команду

cmd.exe /C C:\temp\test.cmd test1.txt test2.txt

not

cmd.exe C:\temp\test.cmd test1.txt test2.txt

Тело вашей хранимой процедуры должно быть изменено на следующее:

  DBMS_SCHEDULER.CREATE_JOB (JOB_NAME    => JOB_ID,
                              JOB_TYPE    => 'executable',
                              JOB_ACTION  => 'c:\windows\system32\cmd.exe',
                              NUMBER_OF_ARGUMENTS => ARGUMENT_COUNT + 2,  -- up to + 2 here
                              AUTO_DROP   => TRUE);
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (JOB_ID, 1, '/C');                -- extra arg
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (JOB_ID, 2, HOST_COMMAND);        -- now arg 2
  FOR CURRENT_ARGUMENT_COUNT IN 1..ARGUMENT_COUNT
  LOOP
    CURRENT_ARGUMENT := GET_DELIMITED_ELEMENT(ARGUMENT_LIST,DELIMITER,CURRENT_ARGUMENT_COUNT);
    -- Change from + 1 to + 2 in the line below:
    DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (JOB_ID, CURRENT_ARGUMENT_COUNT + 2, CURRENT_ARGUMENT);
  END LOOP;
  DBMS_SCHEDULER.RUN_JOB (JOB_ID);

Я внес это изменение в вашу хранимую процедуру, и она сработала, потому что у меня есть база данных для запуска вашего скрипта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...