我有一个oracle sql日期查询,该查询对于Java 7正常工作,但是当对Java 8运行相同的查询时,它将抛出错误,如下所示:
“ not a month
”。
如果我使用查询,例如:
DATA_RECEIVED_MOMENT > TO_DATE ('26-09-18 10:33:43 AM', 'dd-mm-yy HH:MI:SS AM')
它适用于Java 8,但适用于Java 7
DATA_RECEIVED_MOMENT > '26-09-18 10:33:43 AM'
甚至有效。
有人可以帮助解释这背后的原因是否是Java版本差异,其他所有内容都相同。我已经在Java 7中同时运行了查询。
答案 0 :(得分:2)
您必须了解的一件事是,当您编写此代码时:
DATA_RECEIVED_MOMENT > '26-09-18 10:33:43 AM'
您实际上是在说:
DATA_RECEIVED_MOMENT > TO_DATE('26-09-18 10:33:43 AM')
Oracle注意到您正在将字符串与日期进行比较...因此,由于您混合了梨和苹果,因此它隐式调用一个参数 TO_DATE sql函数。
此一参数TO_DATE函数使用由客户端软件设置的默认字符串格式:每个用户会话都可以设置所需的日期格式。没有固定的默认格式,因为它取决于您使用的客户端的语言设置(如果直接在服务器上工作,则取决于服务器操作系统的设置)。
换句话说:当您的查询与Java 7一起使用时,您很幸运,因为JDBC驱动程序可能正好设置了您隐式使用的默认字符串格式。
您使用的日期格式甚至在我的意大利Windows客户端上都无法使用(无需编写Java程序:您可以在SQL plus中尝试使用)
SQL> select 1
2 from dual
3 where sysdate > '26-09-18 10:33:43 AM'
4 /
where sysdate > '26-09-18 10:33:43 AM'
*
ERRORE alla riga 3:
ORA-01843: mese non valido
之所以会发生这种情况,是因为为意大利客户安装程序初始化的默认日期格式为“ DD-MON-RR”(甚至不希望包含时间部分)
这是如何发现会话使用的日期时间格式。
SQL> select *
2 from nls_session_parameters
3 where parameter = 'NLS_DATE_FORMAT'
4 /
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT DD-MON-RR
您可以在Java程序中尝试此查询,以查看Java 8和Java 7之间的不同设置。
我的PC上的其他查询确实起作用:
从对偶中选择1,其中sysdate> '26 -set-18'
并且请注意,“ MON”的意思是“ 当月名称的第3个字符,以客户使用的语言表示”。 所以...如果我将操作系统切换为英语,那将无法正常工作。
因此:您将发现这很可能在您的Java 8应用程序中起作用:
select 1 from dual where sysdate > 'DEC-20-18'
,但是您必须意识到,这仅适用于使用英语在美国安装的PC客户端。例如,在英格兰,他们写月的前一天。
所以好的做法是:
无论如何,更好的选择是第一个,因为它在服务器上产生的负载更少:oracle保留已解析的所有查询的缓存:如果您输入1000次相同的EXACT查询文本(即使参数值是不同),它将在缓存中查找该文本已计算出的执行计划,并将检索执行该查询文本他已经为该查询文本(在这里我简化了事情)的访问计划的数据。
但是,如果您将查询文本中的查询值扩展为文字值,则迫使oracle重新执行文本的解析和执行计划的重新评估(这可能是占用大量CPU的操作)每次执行..而且您还会泛滥我之前描述的查询缓存。