准备好的声明:将时间戳与分钟的粒度进行比较

时间:2015-03-25 15:38:23

标签: java oracle jdbc timestamp prepared-statement

我已经用这样的SQL语句创建了PreparedStatement

SELECT *
FROM MY_TABLE
WHERE MY_DATE = ?

我使用

设置MY_DATE
preparedStatement.setTimestamp(1, myDate);

这样,数据库会检查整个时间戳是否相等。

现在我想将just的粒度减少到几分钟。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:1)

如果使用TRUNC()函数,则可以忽略该值的粒度,低于某个级别。

所以,在你的情况下:

SELECT *
FROM MY_TABLE
WHERE TRUNC(MY_DATE, 'MI') = TRUNC(?, 'MI')

其他粒度可用:有关详细信息,请参阅Oracle's Documentation(默认情况下,截断到相关日期的00:00:00)。

当然,如果您存储的时间戳已被截断为分钟,那么您可以省略TRUNC的左手调用,并利用索引(如果该列上有一个索引)。

答案 1 :(得分:1)

使用 TRUNC 会抑制日期列上的任何常规索引。提高性能的一种方法是创建基于功能的索引

但是,更好的方法是使用显式范围条件

例如,

SELECT *
FROM MY_TABLE
WHERE
  MY_DATE >= TO_DATE('24-MAR-2015','DD-MON-YYYY')
  AND MY_DATE < TO_DATE('24-MAR-2015','DD-MON-YYYY')+1;

或者,

使用 BETWEEN (无论如何,优化程序会将其重写为上述范围条件):

SELECT *
FROM MY_TABLE
WHERE
  MY_DATE BETWEEN TO_DATE('24-MAR-2015','DD-MON-YYYY')
  AND TO_DATE('24-MAR-2015','DD-MON-YYYY') + (1-1/24/60/60);

更多信息

使用范围条件,优化器实际上以下列方式重写查询:

access("MY_DATE">=TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
              "MY_DATE"<TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

并且会有INDEX RANGE SCAN次操作而不是TABLE ACCESS FULL。如果使用 TRUNC ,没有基于函数的索引,这就是优化器应用过滤谓词的方式:

filter(TRUNC(INTERNAL_FUNCTION("MY_DATE"))=TO_DATE(' 2015-03-24 00:00:00',
              'syyyy-mm-dd hh24:mi:ss'))

关于Impact of the TRUNC Function on an Indexed Date Column

的文章