如何解决Oracle DBMS_SCHEDULER.CREATE_JOB问题?

时间:2019-04-04 18:34:06

标签: oracle

我正在尝试从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文件夹的权限更改为所有人的完全访问权限。

不确定在哪里可以找到问题。我该怎么办?

编辑:

它在Windows 2016上的Oracle 12c R2中运行。

1 个答案:

答案 0 :(得分:2)

问题是您没有正确呼叫cmd.exe。您需要在脚本名称之前将/C开关传递到cmd.exe。换句话说,您需要获取数据库以运行命令

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

不是

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);

我对您的存储过程进行了更改,并且它起作用了,因为我有了数据库来运行您的脚本。