从你的输出来看,似乎你已将 START_DATE 定义为时间戳。如果它是普通日期,Oracle 就能够处理隐式转换。但由于它不是,你需要显式地将这些字符串强制转换为日期。
SQL> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss'
2 /
Session altered.
SQL>
SQL> select * from t23
2 where start_date between '15-JAN-10' and '17-JAN-10'
3 /
no rows selected
SQL> select * from t23
2 where start_date between to_date('15-JAN-10') and to_date('17-JAN-10')
3 /
WIDGET START_DATE
Small Widget 15-JAN-10 04.25.32.000
SQL>
但我们仍然只得到一行结果。这是因为START_DATE具有时间元素。如果我们不指定时间组件,Oracle会将其默认为午夜。对于BETWEEN
的from端来说这没问题,但对于until端来说不是:
SQL> select * from t23
2 where start_date between to_date('15-JAN-10')
3 and to_date('17-JAN-10 23:59:59')
4 /
WIDGET START_DATE
Small Widget 15-JAN-10 04.25.32.000
Product 1 17-JAN-10 04.31.32.000
SQL>
编辑
如果您无法传递时间组件,则有几种选择。一种是更改WHERE子句以从条件中删除时间元素:
where trunc(start_date) between to_date('15-JAN-10')
and to_date('17-JAN-10')
这可能会影响性能,因为它会使得基于 START_DATE 的 B-tree 索引失效。你需要构建一个函数基于的索引来代替它。
或者你可以在代码中将时间元素添加到日期中。
where start_date between to_date('15-JAN-10')
and to_date('17-JAN-10') + (86399/86400)
由于这些问题,许多人更喜欢避免使用 BETWEEN
,而是通过检查日期边界来实现:
where start_date >= to_date('15-JAN-10')
and start_date < to_date('18-JAN-10')