Sql 奇怪的预言日期行为

Sql 奇怪的预言日期行为,sql,oracle,Sql,Oracle,我在我们的一个生产数据库中遇到了一个奇怪的问题。长话短说,简单查询: select id, trunc(stdate) from table_name where trunc(stdate) = '05-FEB-09'; 没有返回行。但是, select trunc(stdate) from table_name where id = sought_after_id; 返回的'05-FEB-09'。只有在我尝试之后: update table_name set stdate = '05-

我在我们的一个生产数据库中遇到了一个奇怪的问题。长话短说,简单查询:

select id, trunc(stdate) from table_name where trunc(stdate) = '05-FEB-09';  
没有返回行。但是,

select trunc(stdate) from table_name where id = sought_after_id;
返回的
'05-FEB-09'
。只有在我尝试之后:

update table_name set stdate = '05-FEB-09' where id = sought_after_id;
我的原始查询按预期工作:

select id, trunc(stdate) from table_name where trunc(stdate) = '05-FEB-09';
> sought_after_id, '05-FEB-09'

那么,我的stdate值发生了什么变化

您应该始终将日期与日期(苹果对苹果…)进行比较,而不是依赖于隐式转换

由于
TRUNC(date)
返回一个日期,您应该将其与日期进行比较:

select id, trunc(stdate) from table_name where trunc(stdate) = DATE '2009-02-05'

更新回应Igor的第一条评论:

依赖隐式数据转换使得查询结果依赖于多个会话参数。如果您现在看到的结果与前几天不同,则必须修改其中一个参数。通过不依赖隐式转换,可以使查询“独立于会话”

值得坚持的是,您的第一个查询取决于客户端会话的参数。如果会话修改其默认日期显示设置,则查询将不会返回相同的结果


另一方面,
DD-MON-RR
是一种完全可以接受的日期格式,用于显示,但它并不适合在代码中使用,因为世纪存在歧义,并且您在月份依赖NLS_date_语言参数。

它可能有两种情况。第一个是,YY日期掩码可能会掩盖世纪的不同值;如果不使用
YYYY
指定一个,则默认为当前世纪。第二,Oracle日期包含一个时间元素。如果不指定时间,则默认为午夜

SQL> select * from d
  2  /

D1                ID
--------- ----------
19-JAN-10          1
19-JAN-10          3
19-JAN-10          2

SQL> select * from d
  2  where d1 = to_date('19-JAN-10', 'DD-MON-YY')
  3  /

D1                ID
--------- ----------
19-JAN-10          3


SQL> alter session set nls_date_format='DD-MON-YYYY HH24:MI-SS'
  2  /

Session altered.

SQL> select * from d
  2  /

D1                           ID
-------------------- ----------
19-JAN-1910 00:00-00          1
19-JAN-2010 00:00-00          3
19-JAN-2010 12:00-00          2

SQL>
只有一条记录-#3-与#日期('10年1月19日','DD-MON-YY')匹配,因为#1有不同的世纪,而#2有不同的时间

编辑

我表中的所有行都有相同的 世纪和00:00-00时间元素

现在是这样,但可能只是因为你已经修正了数据。那一天肯定有些不同,否则甲骨文会把它和其他日子一视同仁


通过运行更新,您已经消除了差异。事后我们不可能告诉您数据有什么问题。如果您有审计跟踪,您应该查阅它,因为这将有助于您了解系统的哪个部分插入或更新了带有无效日期掩码的记录,以便您可以修复它。

明确强制转换日期有效吗<代码>截止日期('09年2月5日','DD-MON-YY')我还没有试过铸造。这只是我遇到过的这一行(数百行中的一行)。这个查询是从不同的终端运行的吗?该终端上的NLS日期设置可能不是您通常设置的(从本终端的第一手经验来看)。谢谢,这是一个很好的建议。然而,我这里有一个长时间运行的查询(5年以上),它不仅仅适用于一行。在我的更新之后,一切又恢复正常了。@Igor您的查询已经运行了5年多了。我想你还有其他问题;-):)对不起,我的英语不好。当然,这个查询不需要5年来执行,它只是工作了5年多,没有一个问题。谢谢你的回答。我表中的所有行都有相同的世纪和00:00-00时间元素。我是APC的。如果所讨论的行在您进行更新之前的世纪不正确,那么您将看到这种行为。
SQL> select * from d
  2  /

D1                ID
--------- ----------
19-JAN-10          1
19-JAN-10          3
19-JAN-10          2

SQL> select * from d
  2  where d1 = to_date('19-JAN-10', 'DD-MON-YY')
  3  /

D1                ID
--------- ----------
19-JAN-10          3


SQL> alter session set nls_date_format='DD-MON-YYYY HH24:MI-SS'
  2  /

Session altered.

SQL> select * from d
  2  /

D1                           ID
-------------------- ----------
19-JAN-1910 00:00-00          1
19-JAN-2010 00:00-00          3
19-JAN-2010 12:00-00          2

SQL>