我正在尝试从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中运行。
答案 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);
我对您的存储过程进行了更改,并且它起作用了,因为我有了数据库来运行您的脚本。