代码之家  ›  专栏  ›  技术社区  ›  Igor Drincic

奇怪的预言日期行为

  •  2
  • Igor Drincic  · 技术社区  · 15 年前

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

    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值发生了什么?

    2 回复  |  直到 15 年前
        1
  •  5
  •   Vincent Malgrat    15 年前

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

    自从 TRUNC(date) 返回应将其与日期进行比较的日期:

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

    select id, trunc(stdate) 
      from table_name 
     where trunc(stdate) = TO_DATE('05-FEB-09', 'DD-MON-RR'))
    

    更新 对于igor的第一条评论:

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

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

    在相关的注释中, DD-MON-RR 是完全可以接受的日期格式 显示 但是它不太适合在代码中使用,因为关于世纪有一个歧义,并且您在几个月内依赖于nls-date-u语言参数。

        2
  •  4
  •   APC    15 年前

    可能有两件事。第一个是 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>
    

    只有一条记录匹配 to_date('19-JAN-10', 'DD-MON-YY') 因为1有不同的世纪,而2有不同的时间。

    编辑

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

    嗯,那是真的 现在 ,但可能只是因为您已经修复了数据。这个特别的日期肯定有些不同,否则甲骨文会把它和其他人一样对待。

    通过运行更新,您已经消除了差异。事实上,我们不可能告诉你数据有什么问题。如果您有一个审计跟踪,您应该参考它,因为它将有助于您知道系统的哪个部分插入或更新了一个无效的日期屏蔽记录,所以您可以修复它。