在 Oracle DB 中选择不返回 Date 类型的预期结果

Posted

技术标签:

【中文标题】在 Oracle DB 中选择不返回 Date 类型的预期结果【英文标题】:Select doesn't return expected result with Date type in Oracle DB 【发布时间】:2012-05-10 16:57:51 【问题描述】:

表 my_table 是:

CREATE TABLE MY_TABLE(
ID        NUMBER  NOT NULL,
MY_DATE   DATE    NOT NULL);

键入以下查询:

select sysdate from dual

结果是:

10-MAG-12 21:22:32

请注意,mag = may。

现在,如果我输入这个查询:

select *
from my_table
where my_date <= sysdate

结果是:

9918    10-MAG-12 20:00:00
9915    10-MAG-12 21:00:00
9952    10-MAG-12 22:00:00
9951    10-MAG-12 23:00:00

请注意,在 my_table 中我只有这 4 条记录。为什么我看到所有记录而不是第一条和第二条记录?谢谢。

我使用 Oracle SQL Developer。

编辑:请注意,当我使用 PL/SQL 插入记录时,我会输入如下内容:

nCount NUMBER;
myDate DATE;
stringDate VARCHAR2(255);
BEGIN
nCount := 0;
stringDate := substr(to_char(trunc(sysdate)),0,9);
myDate := to_date(stringDate || ' 20:00:00','dd-mm-yyyy hh24:mi:ss');
for t in (a cursor) loop
   insert into MY_TABLE(ID,MY_DATE)
   values (9918,myDate+(nCount/1440));
   nCount := nCount + 60;
end loop;
END;

【问题讨论】:

看到它正在工作..您的问题令人困惑。 sqlfiddle.com/#!4/4f136/2 @hkutluay 如果我手动插入它可以工作,但我需要按照我编辑的问题所示插入。 【参考方案1】:

我怀疑存储在您表中的数据没有 2012 年。它可能有 0012 年(两千年前)。

当你运行查询时你会看到什么

SELECT id, to_char( my_date, 'dd-mm-yyyy hh24:mi:ss' )
  FROM my_table

我预计年份将是 0012 而不是 2012。原因是您用于插入数据的代码在不使用显式格式掩码的情况下错误地将日期转换为字符串,然后将字符串转换回使用恰好与会话的NLS_DATE_FORMAT 不匹配的显式格式掩码到日期。一般来说,如果您发现自己将日期转换为字符串并返回日期,那么您可能做错了什么。如果您将代码更改为简单地进行日期操作,它将更高效、更健壮且不易出错。

DECLARE
  nCount NUMBER;
  myDate DATE;
BEGIN
  nCount := 0;
  myDate := trunc(sysdate) + interval '20' hour;
  for t in (a cursor) loop
     insert into MY_TABLE(ID,MY_DATE)
       values (9918,myDate+(nCount/1440));
     nCount := nCount + 60;
  end loop;
END;

了解原始代码出错的原因

stringDate := substr(to_char(trunc(sysdate)),0,9);

这需要SYSDATE 并将其截断到当天的午夜。到现在为止还挺好。然后,它调用TO_CHAR 而不使用显式格式掩码。这会导致 Oracle 使用会话的NLS_DATE_FORMAT,这意味着不同的用户使用不同的设置会得到不同的结果。如果您的会话的NLS_DATE_FORMAT 恰好是“dd-mon-rr hh24:mi:ss”,我根据您发布的查询结果猜测,这意味着该字符串有一个两位数的年份。您的 SUBSTR 似乎假设输出只有两位数的年份(如果您有不同的 NLS_DATE_FORMAT,您的 SUBSTR 将产生不同的错误,例如可能从 2012 年的一年中删除 12 年仅 20 个)。

myDate := to_date(stringDate || ' 20:00:00','dd-mm-yyyy hh24:mi:ss');

假设stringDate 类似于10-MAG-12,下一行会生成一个字符串10-MAG-12 20:00:00,然后尝试使用格式掩码dd-mm-yyyy hh24:mi:ss 将其转换为日期。这假设字符串有一个 4 位数的年份,所以当它只找到 2 位数时,它假设您的意思是 12 年,而不是 2012 年。

【讨论】:

非常感谢,这是我的第一个 PL/SQL 代码,我对日期没有那么自信。

以上是关于在 Oracle DB 中选择不返回 Date 类型的预期结果的主要内容,如果未能解决你的问题,请参考以下文章

如果 DATE 具有特定格式(NOT DATE),则返回两个日期之间的天数

Oracle Left Join 导致单行子查询返回多行错误

在查询中比较 oracle 日期时间失败并且不返回任何记录

将 DB2 日期计算转换为 Oracle 语法

使用oracle db的日期函数

处理 Oracle DB 存储的 Java 类中的异常