提交Oracle调度作业时遇PLS-00166错误:日期格式非法
错误原因分析
- NLS_DATE_LANGUAGE依赖问题:
NEXT_DAY函数的星期名称参数(此处的'SUN')是字符串字面量,其有效性完全依赖当前会话的NLS_DATE_LANGUAGE设置。如果数据库会话的语言不是英文,Oracle无法识别'SUN'为合法的星期标识,直接触发PLS-00166格式错误。 - interval参数的解析特性:
DBMS_JOB的interval参数是字符串类型,会在作业执行时重新解析,此时的会话NLS设置可能和提交作业时不同,即使提交时会话语言是英文,后续执行也可能因环境变化触发错误。
解决办法
方法1:使用NLS无关的星期指定方式
将NEXT_DAY中的星期名称替换为带固定语言参数的TO_DATE调用,确保无论会话语言如何,都能正确识别星期:
DBMS_JOB.SUBMIT ( job_number => v_job_ID + 1, what => 'BEGIN'|| v_query ||'END', next_date => TRUNC(NEXT_DAY(SYSDATE, TO_DATE('SUN', 'DY', 'NLS_DATE_LANGUAGE=ENGLISH'))) + 2.5/24, -- 2:30 AM interval => 'NEXT_DAY(TRUNC(SYSDATE), TO_DATE(''SUN'', ''DY'', ''NLS_DATE_LANGUAGE=ENGLISH'')) + 2.5/24', comments => 'Job to run every sunday at 2:30 AM', no_parse => TRUE );
方法2:使用星期数字(需注意NLS_TERRITORY规则)
NEXT_DAY的第二个参数可以接受数字,代表一周中的第几天(1的含义由NLS_TERRITORY决定,比如美国地区1是周日,欧洲部分地区1是周一)。如果确认数据库环境的NLS_TERRITORY固定,可直接用数字:
-- 假设NLS_TERRITORY设置为美国,1代表周日 DBMS_JOB.SUBMIT ( job_number => v_job_ID + 1, what => 'BEGIN'|| v_query ||'END', next_date => TRUNC(NEXT_DAY(SYSDATE, 1)) + 2.5/24, -- 2:30 AM interval => 'NEXT_DAY(TRUNC(SYSDATE), 1) + 2.5/24', comments => 'Job to run every sunday at 2:30 AM', no_parse => TRUE );
额外建议
- 优先选择方法1,因为它不依赖任何NLS环境设置,兼容性更强。
- 提交作业时尽量避免使用依赖会话环境的字面量,确保作业在任何环境下都能稳定执行。
内容的提问来源于stack exchange,提问作者DIPAK SHAH
相关产品推荐
相关产品推荐

