在Oracle数据库中,我们经常利用Date字段来记录日期和时间信息,有时还会在此字段上创建索引以优化查询效率。然而,当我们通过Java程序访问数据库时,常常会使用类似如下的查询语句:select * from table where endDate > ? and endDate < ?。这段代码会通过PreparedStatement预编译,并使用setTimestamp方法将java.util.Date类型转换为java.sql.Timestamp类型作为参数传入。我们通常认为这样的查询应该能够通过索引区间扫描来提高效率。然而,实际情况却并非如此。
Oracle会将SQL语句解释为:select * from table where TO_TIMESTAMP(endDate) > ? and TO_TIMESTAMP(endDate) < ?。这是因为在9.2版本之后,Oracle开始支持timestamp类型,因此它会对传入的参数进行转换。这种转换导致了SQL执行变成了全表扫描,而非我们期望的索引区间扫描。