Oracle Java - 将可选的日期参数添加到 Prepared 语句

Oracle Java - Add optional date parameter to Prepared statement

我想将可选的 "todate" 参数添加到准备好的语句

一种方法是为可选参数添加占位符并在执行前替换它

  where id=? OPTIONAL_SECTION 

例如 OPTIONAL_SECTION 将设置为 TO_DATE <=sysdate -1

更好更正确的方法是绑定可选参数处理空值

where id=? and TO_DATE <= nvl(?, TO_DATE)

有没有更好的方法来处理可选的日期参数? 特别是因为条件可以不相等 ( TO_DATE < ?)

A better and correct way is to bind optional parameter with handling null

这不一定更好或更正确。这是一种不同的方式,但如果它“更好且(更)正确”,那就太糟糕了table。

SQL 查询优化器通常 运行 在任何 ? 参数值已知之前,因此 TO_DATE <= nvl(?, TO_DATE) 无法优化,需要完整的 table扫描,排除 where 子句中的任何其他条件。

但是对于 TO_DATE <= ?,优化器可以使用 TO_DATE 上的索引来对索引进行范围扫描,所以我认为第一个选项可能更好, 取决于可用索引。


condition can be without equal ( TO_DATE < ?)

第二个版本的正确写法是:

where id = ?
  and (? is null or TO_DATE < ?)

您当然必须为 PreparedStatement.

指定两次值

带有可选参数的查询的第一个决定如下:

1) accepatable 对两个/所有选项使用 一个语句

2) 最好为每个选项使用单独的statament

在您的情况下,您有两个参数选项:

id

iddate_parameter

从命名来看,我认为 ID 是 table 的主键,所以它 return 只有一行,并且会是 执行计划中的驱动程序-简单索引访问.

date_parameter只能导致查询return可选无行

在这种情况下,您可以安全地使用决定 1) - 两个选项的一次查询就可以了

但在其他解释中,ID 是具有大量行的 外键 date_parameter 仅用于 return最近的少量行。

在这种情况下,决策 1) aka OR 查询将严重失败。执行计划针对 return 处理大量数据的情况进行了优化,因此您将等待很长时间才能获得少量行。

所以在这种情况下,只有决策 2) 提供了一个高效的解决方案。 简答是根据传入的参数动态生成两个查询

where id=? 

where id=? and data_parameter <= ?

这种方法的技术问题是,查询具有不同数量的绑定变量,这使得 setXXX 变得复杂。

为了避免这个问题,您可以使用 1=1 or 技巧,即 a) 使绑定变量的数量在所有查询中都相等* 并且 b) 消除不必要的一次。

ID 的查询生成为

where id=? and 1=1 or data_parameter <= ?

使用 IDDATE_PARAM 的查询保持不变

where id=? and data_parameter <= ? 

可以找到更多推广这种方法的例子和功劳here and