oracle 10g提交作业功能错误

oracle 10g提交作业功能错误,oracle,oracle10g,jobs,date-arithmetic,Oracle,Oracle10g,Jobs,Date Arithmetic,我正试图在oracle 10g中安排一项作业,但它说: ORA-01846:不是一周中的有效日期 这是我的密码: declare v_job_id1 number(19,0); v_job_id2 number(19,0); begin dbms_job.submit(v_job_id1, 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);', NEXT_DAY(TRUNC(SYSDATE)

我正试图在oracle 10g中安排一项作业,但它说:

ORA-01846:不是一周中的有效日期

这是我的密码:

declare
    v_job_id1 number(19,0);
    v_job_id2 number(19,0);
begin
    dbms_job.submit(v_job_id1, 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);', NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24, NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24 + 7 );
     commit;
end;
/
但这项工作的目的是:

select NEXT_DAY(TRUNC(SYSDATE - 1), 4) + 13/24 from dual;
有什么想法吗

谢谢大家!


Udo

间隔参数必须是一个带有SQL表达式的字符串,由Oracle在计算下次运行的日期和时间时执行

因此,必须引用以下表达式:

dbms_job.submit(
  JOB       =>  v_job_id1, 
  WHAT      => 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);',
  NEXT_DATE => NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24, 
  INTERVAL  => 'NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24 + 7'
);

Interval参数必须是带有SQL表达式的字符串,由Oracle在计算下次运行的日期和时间时执行

因此,必须引用以下表达式:

dbms_job.submit(
  JOB       =>  v_job_id1, 
  WHAT      => 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);',
  NEXT_DATE => NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24, 
  INTERVAL  => 'NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24 + 7'
);

我把它作为一个答案而不是一个评论来发布,以允许更好的代码格式。ThinkJet关于间隔参数的评论是正确的,我仍然认为您的问题与“4”参数到下一天有关-例如,以下代码有效:

SQL> declare
  2      v_job_id1 number(19,0);
  3      v_job_id2 number(19,0);
  4  begin
  5      dbms_job.submit(v_job_id1,
  6        'begin null; end;',
  7        NEXT_DAY(TRUNC(SYSDATE), 'Thursday') + 13/24,
  8        'NEXT_DAY(TRUNC(SYSDATE), '||chr(39)||'Thursday'||chr(39)||') + 13/24 + 7' );
  9       commit;
 10  end;
 11  /

PL/SQL procedure successfully completed.

我把它作为一个答案而不是一个评论来发布,以允许更好的代码格式。ThinkJet关于间隔参数的评论是正确的,我仍然认为您的问题与“4”参数到下一天有关-例如,以下代码有效:

SQL> declare
  2      v_job_id1 number(19,0);
  3      v_job_id2 number(19,0);
  4  begin
  5      dbms_job.submit(v_job_id1,
  6        'begin null; end;',
  7        NEXT_DAY(TRUNC(SYSDATE), 'Thursday') + 13/24,
  8        'NEXT_DAY(TRUNC(SYSDATE), '||chr(39)||'Thursday'||chr(39)||') + 13/24 + 7' );
  9       commit;
 10  end;
 11  /

PL/SQL procedure successfully completed.

我无法解释为什么会发生这种情况,但Oracle接受普通SQL中无效的
次日(…)
调用语法

但不是在PL/SQL代码中。试试这个:

declare 
  d date;
begin
  d := NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24 + 7;
end;
你得到了完美的ORA-01846错误

Oracle建议在将下一天调用为“AMERICAN”并在计算后返回之前,先切换NLS_DATE_LANGUAGE会话参数

例如:

DECLARE
FUNCTION get_next_day(dn IN VARCHAR2,ln IN VARCHAR2) RETURN DATE IS
CURSOR cr1 IS
SELECT value
  FROM nls_session_parameters
 WHERE parameter = 'NLS_DATE_LANGUAGE';
CURSOR cr2(dn1 IN VARCHAR2) IS
SELECT next_day(SYSDATE,UPPER(dn1))
  FROM dual;
day DATE;
old_date_lang varchar2(128);
BEGIN
  OPEN cr1;
  FETCH cr1 INTO old_date_lang;
  CLOSE cr1;
  dbms_session.set_nls('NLS_DATE_LANGUAGE',ln);
  OPEN cr2(dn);
  FETCH cr2 INTO day;
  CLOSE cr2;
  dbms_session.set_nls('NLS_DATE_LANGUAGE', old_date_lang);
  RETURN (day);
END;
BEGIN
  dbms_output.put_line(TO_CHAR(get_next_day('MONDAY','AMERICAN'),'DAY dd/mm/yyyy'));
END;
从我的观点来看,最好避免使用NLS感知功能,但一周中的一天NLS取决于定义:在某些国家,一周从周日开始,在其他国家,从周一开始

您可以尝试使用带有“D”选项的
TRUNC()
函数来降低NLS效果:

select 
  NEXT_DAY(TRUNC(SYSDATE), 4)          as D1, 
  NEXT_DAY(TRUNC(SYSDATE), 'THU')      as D2, 
  case     
    -- next Thursday on this week
    when (TRUNC(SYSDATE,'D') + 4) > trunc(sysdate) then (TRUNC(SYSDATE,'D') + 4)
    -- next Thursday on next week
    else (TRUNC(SYSDATE,'D') + 4) + 7 
  end                                  as D3
from dual
在您的情况下,看起来是这样的:

dbms_job.submit(
  JOB       =>  v_job_id1, 
  WHAT      => 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);',
  NEXT_DATE => (
                 case     
                   -- next Thursday on this week
                   when (TRUNC(SYSDATE,'D') + 4) > trunc(sysdate) then (TRUNC(SYSDATE,'D') + 4)
                   -- next Thursday on next week
                   else (TRUNC(SYSDATE,'D') + 4) + 7 
                 end               
               ), 
  INTERVAL  => '
      case     
        when (TRUNC(SYSDATE,''D'') + 4) > trunc(sysdate) then (TRUNC(SYSDATE,''D'') + 4)
        else (TRUNC(SYSDATE,''D'') + 4) + 7 
      end               
  '
);

更新:

完美的解决方法是从当前NLS设置中获取日期名称,并将其用作日期名称。 因为2010年8月12日肯定是星期四,所以您可以使用它作为基准日期来获取星期几名称:

select to_char(to_date('20100812','yyyymmdd'), 'DAY') from dual  
然后将名称添加到函数调用,而不是
4
常量:

dbms_job.submit(
  JOB       =>  v_job_id1, 
  WHAT      => 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);',
  NEXT_DATE => NEXT_DAY(TRUNC(SYSDATE), to_char(to_date('20100812','yyyymmdd'), 'DAY')) + 13/24, 
  INTERVAL  => 'NEXT_DAY(TRUNC(SYSDATE), to_char(to_date(''20100812'',''yyyymmdd''), ''DAY'')) + 13/24 + 7'
);

我无法解释为什么会发生这种情况,但Oracle接受普通SQL中无效的
次日(…)
调用语法

但不是在PL/SQL代码中。试试这个:

declare 
  d date;
begin
  d := NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24 + 7;
end;
你得到了完美的ORA-01846错误

Oracle建议在将下一天调用为“AMERICAN”并在计算后返回之前,先切换NLS_DATE_LANGUAGE会话参数

例如:

DECLARE
FUNCTION get_next_day(dn IN VARCHAR2,ln IN VARCHAR2) RETURN DATE IS
CURSOR cr1 IS
SELECT value
  FROM nls_session_parameters
 WHERE parameter = 'NLS_DATE_LANGUAGE';
CURSOR cr2(dn1 IN VARCHAR2) IS
SELECT next_day(SYSDATE,UPPER(dn1))
  FROM dual;
day DATE;
old_date_lang varchar2(128);
BEGIN
  OPEN cr1;
  FETCH cr1 INTO old_date_lang;
  CLOSE cr1;
  dbms_session.set_nls('NLS_DATE_LANGUAGE',ln);
  OPEN cr2(dn);
  FETCH cr2 INTO day;
  CLOSE cr2;
  dbms_session.set_nls('NLS_DATE_LANGUAGE', old_date_lang);
  RETURN (day);
END;
BEGIN
  dbms_output.put_line(TO_CHAR(get_next_day('MONDAY','AMERICAN'),'DAY dd/mm/yyyy'));
END;
从我的观点来看,最好避免使用NLS感知功能,但一周中的一天NLS取决于定义:在某些国家,一周从周日开始,在其他国家,从周一开始

您可以尝试使用带有“D”选项的
TRUNC()
函数来降低NLS效果:

select 
  NEXT_DAY(TRUNC(SYSDATE), 4)          as D1, 
  NEXT_DAY(TRUNC(SYSDATE), 'THU')      as D2, 
  case     
    -- next Thursday on this week
    when (TRUNC(SYSDATE,'D') + 4) > trunc(sysdate) then (TRUNC(SYSDATE,'D') + 4)
    -- next Thursday on next week
    else (TRUNC(SYSDATE,'D') + 4) + 7 
  end                                  as D3
from dual
在您的情况下,看起来是这样的:

dbms_job.submit(
  JOB       =>  v_job_id1, 
  WHAT      => 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);',
  NEXT_DATE => (
                 case     
                   -- next Thursday on this week
                   when (TRUNC(SYSDATE,'D') + 4) > trunc(sysdate) then (TRUNC(SYSDATE,'D') + 4)
                   -- next Thursday on next week
                   else (TRUNC(SYSDATE,'D') + 4) + 7 
                 end               
               ), 
  INTERVAL  => '
      case     
        when (TRUNC(SYSDATE,''D'') + 4) > trunc(sysdate) then (TRUNC(SYSDATE,''D'') + 4)
        else (TRUNC(SYSDATE,''D'') + 4) + 7 
      end               
  '
);

更新:

完美的解决方法是从当前NLS设置中获取日期名称,并将其用作日期名称。 因为2010年8月12日肯定是星期四,所以您可以使用它作为基准日期来获取星期几名称:

select to_char(to_date('20100812','yyyymmdd'), 'DAY') from dual  
然后将名称添加到函数调用,而不是
4
常量:

dbms_job.submit(
  JOB       =>  v_job_id1, 
  WHAT      => 'CTX_DDL.OPTIMIZE_INDEX(''PSO_KEYWORD_SEARCH_IDX'', ''FULL'', 45);',
  NEXT_DATE => NEXT_DAY(TRUNC(SYSDATE), to_char(to_date('20100812','yyyymmdd'), 'DAY')) + 13/24, 
  INTERVAL  => 'NEXT_DAY(TRUNC(SYSDATE), to_char(to_date(''20100812'',''yyyymmdd''), ''DAY'')) + 13/24 + 7'
);

确保您正在根据区域设置使用日期。 例如:- “星期日”应该用德语写成“桑塔格”。
我曾经遇到过类似的问题p

确保您根据区域设置使用当天。 例如:- “星期日”应该用德语写成“桑塔格”。
我曾经遇到过类似的问题p

我从未见过数字用作下一天的第二个参数,尽管正如您在SELECT语句中所指出的那样。你的意思是星期四吗?如果你用字符串“星期四”而不是4会怎么样?@dpbradley:它在一个独立的句子中起作用。我不能使用文字,因为我在西班牙,“日”取决于nls。所以,如果nls参数在生产环境中与dev不同,我可能会遇到问题。但是不管nls是什么,4都应该起作用。我从来没有见过一个数字用作下一天的第二个参数,尽管正如您在SELECT语句中指出的那样。你的意思是星期四吗?如果你用字符串“星期四”而不是4会怎么样?@dpbradley:它在一个独立的句子中起作用。我不能使用文字,因为我在西班牙,“日”取决于nls。所以,如果nls参数在生产环境中与dev不同,我可能会遇到问题。但不管nls如何,4都应该起作用。它一直说这不是有效的一天。无论如何,谢谢你。它一直在说这不是有效的一天。无论如何,谢谢你。@ThinkJet:这仍然取决于nls。有没有办法将作业设置为在每个星期四的某个给定时间(即下午1点)运行?Thanks@ThinkJet-我认为从SQL发出调用与从PL/SQL发出调用的区别在于,在PL/SQL中,您使用的是数据库的NLS参数,而不是客户端设置。@ThinkJet:非常聪明的解决方案!多谢各位@布莱德利和思捷:谢谢@布莱德利:4号不是,但朱维斯是。所以,如果我输入4,它是Jueves,也是星期四,至少,据我所知,当我在那个解决方案中工作时。4是数字,不是一周中任何一天的有效缩写。如果您阅读官方文档()的话,就不可能用日期数代替日期名称…@ThinkJet:这仍然取决于nls。有没有办法将作业设置为在每个星期四的某个给定时间(即下午1点)运行?Thanks@ThinkJet-我认为从SQL发出调用与从PL/SQL发出调用的区别在于,在PL/SQL中,您使用的是数据库的NLS参数,而不是客户端设置。@ThinkJet:非常聪明的解决方案!多谢各位@布莱德利和思捷:谢谢@布莱德利:4号不是,但朱维斯是。所以,如果我输入4,它是Jueves,也是星期四,至少,据我所知,当我在那个解决方案中工作时。4是数字,不是一周中任何一天的有效缩写。如果你阅读了官方文件(),就不可能用一天的编号来代替一天的名称…@dpbradley:谢谢