我正在尝试在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;
任何想法?
谢谢!
乌
答案 0 :(得分:2)
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'
);
答案 1 :(得分:1)
我将此作为答案而不是评论发布,以便更好地进行代码格式化。 ThinkJet关于interval参数的评论是一个有效点,我仍然认为你的问题与NEXT_DAY的'4'arg有关 - 例如,这段代码有效:
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.
答案 2 :(得分:1)
我无法解释为什么会发生这种情况,但Oracle在纯SQL中接受无效的NEXT_DAY(...)
调用语法。
但不是PL / SQL代码。试试这个:
declare
d date;
begin
d := NEXT_DAY(TRUNC(SYSDATE), 4) + 13/24 + 7;
end;
你得到了完美的ORA-01846错误。
Oracle建议在将NEXT_DAY调用为“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设置中获取当天的名称,并将其用作日期名称。 因为8月12日至2010年肯定是星期四你可以用它作为基准日期来获得星期几的名字:
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'
);
答案 3 :(得分:1)
确保您根据区域设置使用该日期。 对于Ex: - “星期天”的那一天应该用德语写成“Sonntag”。 我遇到过类似的问题..:p