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 不是有效月份 - 比较日期的主要内容,如果未能解决你的问题,请参考以下文章