您有两种方法来处理可选输入参数。
更简单的方式是使用静态 SQL 并为缺失的参数提供 default 值,以便获得所有匹配项。
在这里,您只需将边界设置为可能的最小和最大 DATE。
select *
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between nvl($P{DATE_START},date'1900-01-01')
and nvl($P{DATE_END},date'2200-01-01')
更高级的方式由Tom Kyte推广,基于使用动态SQL。
如果提供了参数,您将生成带有BETWEEN 谓词的普通SQL:
select *
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between $P{DATE_START} and $P{DATE_END}
如果参数丢失(即NULL被传递),您将生成一个不同的SQL,如下所示。
select *
from customer
where customer_id = $P{CLIENT_ID}
and (1=1 or datetrx between $P{DATE_START} and $P{DATE_END})
请注意,
1) 两个查询变体中绑定变量的数量相同,这很重要,因为您可以使用相同的 setXXXX 语句
2) 由于 shortcut 1 = 1 or 是 between 谓词被忽略,即考虑所有日期。
应该使用哪个选项?
对于简单的查询会有很小的差异,但是对于具有多个缺少参数和大数据选项的复杂查询,首选动态 SQL 方法。
原因是,使用静态 SQL,您对更多不同的查询使用相同的语句 - 这里一个用于访问 with 数据范围,另一个用于访问 没有 数据范围。
动态选项为每次访问生成不同的 SQL。
你可以在execution plans看到它:
访问日期范围
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 22 | 1 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
|* 2 | INDEX RANGE SCAN| CUST_IDX1 | 1 | 22 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_DATE(:1)<=TO_DATE(:2))
2 - access("CUSTOMER_ID"=1 AND "DATETRX">=:1 AND "DATETRX"<=:2)
无数据范围的访问
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 22 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| CUST_IDX1 | 1 | 22 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("CUSTOMER_ID"=1)
两个语句产生不同的执行计划,针对输入参数进行了优化。在静态选项中,对于所有可能导致问题的输入,必须共享相同的执行计划。