Sql 在Oracle中对日期使用trunc函数的原因

Sql 在Oracle中对日期使用trunc函数的原因,sql,oracle,Sql,Oracle,我目前在Oracle数据库的一个项目中工作。我在应用程序代码中观察到,日期几乎从未直接使用过。相反,它们总是与trunc函数(trunc(SYSDATE)、trunc(event_date)等)一起使用 有人能解释一下使用trunc函数而不是直接使用日期的原因吗?您可以使用trunc()函数删除日期的时间成分。默认情况下,Oracle中的date数据类型同时存储日期和时间 trunc()函数还接受一个format参数,因此您可以删除日期的其他组件,而不仅仅是时间。例如,您可以精确到最近的小时。但

我目前在Oracle数据库的一个项目中工作。我在应用程序代码中观察到,日期几乎从未直接使用过。相反,它们总是与trunc函数(trunc(SYSDATE)、trunc(event_date)等)一起使用

有人能解释一下使用trunc函数而不是直接使用日期的原因吗?

您可以使用
trunc()
函数删除日期的时间成分。默认情况下,Oracle中的
date
数据类型同时存储日期和时间

trunc()
函数还接受一个format参数,因此您可以删除日期的其他组件,而不仅仅是时间。例如,您可以精确到最近的小时。但是,如果没有格式,目的是删除时间组件。

您可以使用
trunc()
函数删除日期的时间组件。默认情况下,Oracle中的
date
数据类型同时存储日期和时间


trunc()
函数还接受一个format参数,因此您可以删除日期的其他组件,而不仅仅是时间。例如,您可以精确到最近的小时。但是,如果没有格式,则目的是删除时间组件。

Oracle中的日期不仅有日期部分,还有时间部分。这可能导致查询数据时出现令人惊讶的结果,例如查询

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'  
其他不太常用的解决此问题的方法包括:

  • 将带有
    的两个日期转换为_char('YYYY-MM-DD')
    并检查是否相等
  • 使用中间条款:
    其中dt介于日期“2014-06-25”和日期“2014-06-26”之间

在Oracle中,日期不仅有日期部分,还有时间部分。这可能导致查询数据时出现令人惊讶的结果,例如查询

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'  
其他不太常用的解决此问题的方法包括:

  • 将带有
    的两个日期转换为_char('YYYY-MM-DD')
    并检查是否相等
  • 使用中间条款:
    其中dt介于日期“2014-06-25”和日期“2014-06-26”之间

如果表中的列(例如event_date)已编制索引,则应避免在该列上使用trunc,因为如果这样做,Oracle将无法使用该索引(否则,可以创建基于函数的索引)

所以不要这样做:

挑选* 从mytable 其中trunc(事件日期)<日期'2014-01-01'

但是相反,你应该这样做

挑选* 从mytable 其中事件日期<日期'2014-01-02'


在第二种情况下,Oracle可以在事件日期对索引执行范围扫描,在第一种情况下,它必须执行完整的表扫描。

如果表中的列(例如事件日期)被索引,则避免在列上使用trunc,因为如果这样做,Oracle将无法使用索引(否则,可以创建基于函数的索引)

所以不要这样做:

挑选* 从mytable 其中trunc(事件日期)<日期'2014-01-01'

但是相反,你应该这样做

挑选* 从mytable 其中事件日期<日期'2014-01-02'


在第二种情况下,Oracle可以在事件日期对索引执行范围扫描,在第一种情况下,它必须执行完整的表扫描。

因为Oracle中的日期也包含时间部分。我猜开发人员希望确保在与“real”datesTRUNC()进行比较时忽略此时间,并且还接受用于重置其他日期组件的可选参数,因为Oracle中的
date
也包含时间部分。我猜开发人员希望确保在与“real”datesTRUNC()进行比较时忽略此时间,同时也接受用于重置其他日期组件的可选参数