ORA-01855: AM/A.M. or PM/P.M. required问题排查与解析

ORA-01855: AM/A.M. or PM/P.M. required问题排查与解析


【转自】 http://271788203.iteye.com/blog/688303

1.【问题现象】
在中文Windows环境的SQL*Plus中使用如下日期操作SQL时报错。具体报错信息如下:
sec@ora10g> insert into t values (TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM'));
insert into t values (TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM'))
                               *
第 1 行出现错误:
ORA-01855: AM/A.M. or PM/P.M. required

sec@ora10g> select TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM') from dual;
select TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM') from dual
                *
第 1 行出现错误:
ORA-01855: AM/A.M. or PM/P.M. required

2.【问题原因】
在本地NLS_DATE_LANGUAGE参数指定的语言中没有找到“AM”这样的时间定义,也就是说在具体的国家语言下此类“AM”的定义是不相同的,比如,在中文“SIMPLIFIED CHINESE”中就应该指定为“上午/下午”,在美国的语言中就应该指定为“A.M. / P.M.”,在英国语言或西欧语言中就要指定为“AM/PM”。注意其中的区别。

这里给出一种查询NLS_DATE_LANGUAGE参数的方法:
sec@ora10g> col PARAMETER for a30
sec@ora10g> col VALUE for a30
sec@ora10g> select * from v$nls_parameters;

PARAMETER                      VALUE
------------------------------ ------------------------------
NLS_LANGUAGE                   SIMPLIFIED CHINESE
NLS_TERRITORY                  CHINA
NLS_CURRENCY                   ¥
NLS_ISO_CURRENCY               CHINA
NLS_NUMERIC_CHARACTERS         .,
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              SIMPLIFIED CHINESE
NLS_CHARACTERSET               AL32UTF8
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY              ¥
NLS_NCHAR_CHARACTERSET         UTF8
NLS_COMP                       BINARY
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE

已选择19行。

3.【问题处理】 方法很简单,第一类处理方法就是严格按照具体国家语言的定义格式书写特定的时间字符串,另一类处理方法是修改NLS_DATE_LANGUAGE参数以便适应某一种日期字符串的写法。下面从这两类处理思想出发,给出三种可行的处理方法。
1)第一种方法:将原字符串中的“AM”修改为中国特色的的“上午”
sec@ora10g> select TO_Date( '22/10/2009 12:00:00 上午', 'DD/MM/YYYY HH:MI:SS AM') from dual;

TO_DATE('22/10
--------------
22-10月-09

sec@ora10g> alter session set NLS_DATE_FORMAT='MM/DD/YYYY HH:MI:SS AM';

会话已更改。

sec@ora10g> select TO_Date( '22/10/2009 12:00:00 上午', 'DD/MM/YYYY HH:MI:SS AM') from dual;

TO_DATE('22/10/200912:00
------------------------
10/22/2009 12:00:00 上午

2)第二种处理方法:直接在session中修改NLS_DATE_LANGUAGE参数,即刻生效。
(1)修改NLS_DATE_LANGUAGE为“AMERICAN”
sec@ora10g> alter session set NLS_DATE_LANGUAGE = 'AMERICAN';

会话已更改。

(2)再一次尝试查询,此时已经不再报错
sec@ora10g> select TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM') from dual;

TO_DATE('10/
------------
22-OCT-09

(3)格式化一下日期格式,以便更加清晰的查看结果。
sec@ora10g> alter session set NLS_DATE_FORMAT='MM/DD/YYYY HH:MI:SS AM';

会话已更改。

sec@ora10g> select TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM') from dual;

TO_DATE('10/22/200912:
----------------------
10/22/2009 12:00:00 AM

3)第三种方法:修改Windows注册表中的NLS_LANG参数,以便达到迂回的修改NLS_DATE_FORMAT参数的目的
(1)进入Windows注册表方法
点击Windows操作系统的左下角的“开始”(“start”),然后点击“运行”(Run),最后输入“regedit”回车后便可进入到注册表界面。

(2)在注册表中按照下面的过程导航,即可定位到NLS_LANG变量
“My Computer” --> “HKEY_LOCAL_MACHINE” --> “SOFTWARE” --> “ORACLE” --> “KEY-OraDb10g_home1”
此时在注册表的右侧就能发现“NLS_LANG”的身影了

(3)双击“NLS_LANG”,把内容替换为“AMERICAN_AMERICA.ZHS16GBK”或“AMERICAN_CHINA.ZHS16GBK”即可(NLS_LANG的第一部分“语言”起作用)。

(4)验证查询
sec@ora10g> select TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM') from dual;

TO_DATE('10/
------------
22-OCT-09

sec@ora10g> alter session set NLS_DATE_FORMAT='MM/DD/YYYY HH:MI:SS AM';

Session altered.

sec@ora10g> select TO_Date( '10/22/2009 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM') from dual;

TO_DATE('10/22/200912:
----------------------
10/22/2009 12:00:00 AM

4.小结
Oracle的日期操作本身相对其他数据类型操作来说复杂很多,在日常的使用过程中要多加总结与记录。
鉴于本文中提到的问题,在书写脚本的时候或使用工具生成脚本的时候,一定要注意脚本中日期类字符串的书写格式。以防因此导致数据无法录入。

你可能感兴趣的:(ORA-01855: AM/A.M. or PM/P.M. required问题排查与解析)