ORA-01843 不是有效月份 - 比较日期

Posted

技术标签:

【中文标题】ORA-01843 不是有效月份 - 比较日期【英文标题】:ORA-01843 not a valid month- Comparing Dates 【发布时间】:2014-02-05 02:10:50 【问题描述】:

我在尝试从按日期过滤的表中选择数据时遇到问题。

例如:

SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = '23/04/49';

Oracle 错误是:

Informe de error:
Error SQL: ORA-01843: mes no válido
01843. 00000 -  "not a valid month"
*Cause:    
*Action:

可能是表的源数据损坏了,在这种情况下:

我该如何解决这个问题? 我可以将此日期更改为空吗?

这次选择的结果,select * from nls_session_parameters;,是:

PARAMETER                      VALUE                                  
------------------------------ ----------------------------------------
NLS_LANGUAGE                   SPANISH                                  
NLS_TERRITORY                  SPAIN                                    
NLS_CURRENCY                   ¿                                        
NLS_ISO_CURRENCY               SPAIN                                    
NLS_NUMERIC_CHARACTERS         ,.                                       
NLS_CALENDAR                   GREGORIAN                                
NLS_DATE_FORMAT                DD/MM/RR                                 
NLS_DATE_LANGUAGE              SPANISH                                  
NLS_SORT                       SPANISH                                  
NLS_TIME_FORMAT                HH24:MI:SSXFF                            
NLS_TIMESTAMP_FORMAT           DD/MM/RR HH24:MI:SSXFF                   
NLS_TIME_TZ_FORMAT             HH24:MI:SSXFF TZR                        
NLS_TIMESTAMP_TZ_FORMAT        DD/MM/RR HH24:MI:SSXFF TZR               
NLS_DUAL_CURRENCY              ¿                                        
NLS_COMP                       BINARY                                   
NLS_LENGTH_SEMANTICS           BYTE                                     
NLS_NCHAR_CONV_EXCP            FALSE 

【问题讨论】:

日期的使用格式似乎是美国格式:'月/日/年',所以第 23 个月是错误的。尝试使用“04/23/49” 日期的格式是'DD/MM/YY',如果尝试改变'MM/DD/YY'的格式也是一样的。 【参考方案1】:

你应该使用to_date函数(oracle/functions/to_date.php

SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49', 'DD/MM/YY');

【讨论】:

我会说:应该使用。比较日期时,请始终使用格式。否则它会在某个系统的某个地方出错。 是的,雷内。但无论有无格式,有无 TO_DATE 函数,都一样。错误是一样的 --> 01843. 00000 - “不是一个有效的月份”。 您使用的列是日期类型的“mytable.datein”吗? 是的,列类型是 DATE 并且是 NULLABLE。 那么请用 to_date 发布声明,这仍然给你一个例外。【参考方案2】:

您正在将日期列与字符串文字进行比较。在这种情况下,Oracle 会尝试使用默认日期格式将您的文字转换为日期。 依赖这种行为是一种不好的做法,因为如果 DBA 更改了某些配置、Oracle 在未来的修订版中破坏了某些东西等,此默认值可能会发生变化。

相反,您应该始终将文字显式转换为日期并说明您使用的格式:

SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49','MM/DD/YY');

【讨论】:

当然是 Mureinik,但是如果您有一个日期为 23/04/49 的表格并尝试使用之前的选择进行搜索,您会得到同样的错误吗? @Davidin073 日期未存储为 23/04/49。这只是它的一个字符串表示。【参考方案3】:

如果您不需要检查确切的时间戳,请使用

SELECT * FROM MYTABLE WHERE trunc(DATEIN) = TO_DATE('23-04-49','DD-MM-YY');

否则,您可以使用

SELECT * FROM MYTABLE WHERE DATEIN = TO_DATE('23-04-49 20:18:07','DD-MM-YY HH24:MI:SS');

这里,你使用硬编码日期,如果你直接比较,那么你必须使用 DD-MM-YY HH24:MI:SS 否则你可能会得到 ORA-01849: hour must be between 1 and 12.

【讨论】:

【参考方案4】:

我知道这有点晚了,但我遇到了类似的问题。 SQL*Plus 执行查询成功,但Oracle SQL Developer 显示ORA-01843: not a valid month error.

SQL*Plus 似乎知道我使用的日期格式有效,而 Oracle SQL Developer 需要明确告知我的日期格式。

SQL*Plus statement

select count(*) from some_table where DATE_TIME_CREATED < '09-12-23';

VS

Oracle SQL Developer statement

 select count(*) from some_table where DATE_TIME_CREATED < TO_DATE('09-12-23','RR-MM-DD');

【讨论】:

【参考方案5】:

以防万一,我通过检查服务器日期格式解决了这个问题:

SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';

然后通过使用以下比较(左侧字段为日期+时间):

AND EV_DTTM >= ('01-DEC-16')

我正在尝试使用 TO_DATE 进行此操作,但一直出现错误。但是当我将我的字符串与NLS_DATE_FORMAT 匹配并删除TO_DATE 时,它起作用了......

【讨论】:

【参考方案6】:

在对您提到的一个答案的评论中,使用格式的 to_date 没有帮助。在另一条评论中,您解释说该表是通过 DBLINK 访问的。

显然,其他系统包含 Oracle 无法接受的无效日期。在其他 dbms(或任何您 dblink 到的)中修复此问题,您的查询将正常工作。

话虽如此,我同意其他人的观点:始终使用 to_date 将字符串文字转换为日期的格式。一年也不要只使用两位数。例如,“23/04/49”在您的系统中表示 2049(格式 RR),但它会让读者感到困惑(正如您从建议使用 YY 格式的答案中看到的那样)。

【讨论】:

我无法访问源表。所以它不可能修改这些数据。它与年份无关的数据,因为错误在月份。 不,也许你不能。但是您也许可以报告此问题,以便有人 可以在其他系统中解决此问题。至于年份:与错误无关。这只是一般性建议。 好的,我会报告这个错误。感谢您的推荐,Thorsten,但它通常必须使用其他人以前创建的代码并且不能修改某些实现。【参考方案7】:

如果源日期包含分钟和秒部分,您的日期比较将失败。 您还需要使用 to_char 和目标日期将源日期转换为所需的格式。

【讨论】:

【参考方案8】:

ALTER 会话集 NLS_LANGUAGE='AMERICAN';

【讨论】:

感谢您的回答,但能否请您提供一些背景信息?如果可以的话,解释为什么这可以解决问题。 他在开玩笑,开玩笑说 SQL 环境设置为 Español。【参考方案9】:

如果你使用的是命令行工具,那么你也可以在shell中设置。

在 linux 上,使用 sh 类型的 shell,您可以这样做:

export NLS_TIMESTAMP_FORMAT='DD/MON/RR HH24:MI:SSXFF'

然后你可以使用命令行工具,它会使用指定的格式:

/path/to/dbhome_1/bin/sqlldr user/pass@host:port/service control=table.ctl direct=true

【讨论】:

【参考方案10】:

尝试使用:

SELECT *
FROM MYTABLE
WHERE MYTABLE.DATEIN is not null 
AND MYTABLE.DATEIN = '23/04/49';

【讨论】:

【参考方案11】:

虽然使用 TO_DATE 的答案是正确的,但我更喜欢使用 ANSI SQL 格式的日期: 日期 = 日期'1949-04-23'

它适用于 Oracle 和其他符合 ANSI SQL 的 DBMS。如果您的应用程序与 DBMS 无关,这一点尤其重要。

【讨论】:

【参考方案12】:

使用month 作为字符串。

例子:

(12-Apr-2002) or (12-April-2002)

【讨论】:

以上是关于ORA-01843 不是有效月份 - 比较日期的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别