我目前正在Oracle数据库的一个项目中工作。我在应用程序代码中观察到日期几乎从不直接使用。相反,它们总是与trunc函数一起使用(TRUNC(SYSDATE),TRUNC(event_date)等)。
任何人都可以解释使用截断函数而不是直接使用日期的原因吗?
答案 0 :(得分:4)
Oracle中的DATE
不仅包含日期部分,还包含时间部分。这可以在查询数据时产生令人惊讶的结果,例如,查询
with v_data(pk, dt) as (
select 1, to_date('2014-06-25 09:00:00', 'YYYY-MM-DD hh24:mi:ss') from dual union all
select 2, to_date('2014-06-26 09:00:00', 'YYYY-MM-DD hh24:mi:ss') from dual union all
select 3, to_date('2014-06-27 09:00:00', 'YYYY-MM-DD hh24:mi:ss') from dual)
select * from v_data where dt = date '2014-06-25'
将不返回任何行,因为您将在午夜时分与2014-06-25进行比较。
通常的解决方法是使用TRUNC()
来摆脱时间部分:
with v_data(pk, dt) as (
select 1, to_date('2014-06-25 09:00:00', 'YYYY-MM-DD hh24:mi:ss') from dual union all
select 2, to_date('2014-06-26 09:00:00', 'YYYY-MM-DD hh24:mi:ss') from dual union all
select 3, to_date('2014-06-27 09:00:00', 'YYYY-MM-DD hh24:mi:ss') from dual)
select * from v_data where trunc(dt) = date '2014-06-25'
其他一些不经常使用的解决此问题的方法包括:
to_char('YYYY-MM-DD')
转换这两个日期并检查相等性WHERE dt between date '2014-06-25' and date '2014-06-26'
答案 1 :(得分:2)
您使用trunc()
功能删除日期的时间部分。默认情况下,Oracle中的date
数据类型存储日期和时间。
trunc()
函数也采用格式参数,因此您可以删除日期的其他组件,而不仅仅是时间。例如,您可以截断到最近的小时。但是,如果没有格式,目的是删除时间组件。
答案 2 :(得分:1)
如果您的表中的列(例如event_date)已编入索引,那么请避免在列上使用trunc,因为如果您这样做,那么Oracle就无法使用索引(否则,您可以创建基于函数的索引)
所以不要这样做:
选择* 来自mytable trunc(event_date)<日期' 2014-01-01'
但改为
选择* 来自mytable event_date<日期' 2014-01-02'
在第二种情况下,Oracle可以对event_date上的索引进行范围扫描,在第一种情况下,它必须进行全表扫描。