Oracle 未输入参数时,忽略where子句中的日期范围参数
未输入参数时,忽略where子句中的日期范围参数。对于我的约会范围,我使用介于 这些参数是从jasper报告中输入的Oracle 未输入参数时,忽略where子句中的日期范围参数,oracle,Oracle,未输入参数时,忽略where子句中的日期范围参数。对于我的约会范围,我使用介于 这些参数是从jasper报告中输入的 SELECT * from customer where client_id = $P{CLIENT_ID} AND (Account_id = CASE WHEN $P{Account_ID}>0 THEN $P{Account_ID} ELSE
SELECT *
from customer
where client_id = $P{CLIENT_ID}
AND (Account_id = CASE WHEN $P{Account_ID}>0
THEN $P{Account_ID}
ELSE Account_ID END
OR Account_ID IS NULL )
AND datetrx BETWEEN $P{DATE_START} AND $P{DATE_END}
如果未输入日期,则报告应包含任何日期的记录,因为未输入日期范围您有两种可能接近可选输入参数 更简单的方法是使用静态SQL并为缺少的参数提供默认值,以便获得所有匹配项 在这里,您可以简单地将边界设置为可能的最小和最大日期
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')
更高级的方法是由推广的,并基于使用动态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) 由于快捷方式1=1或
忽略了between
谓词,即考虑所有日期
应该使用哪个选项?
对于简单的查询,会有较小的差异,但是对于具有多个缺少参数和大数据选项的复杂查询,最好使用动态SQL方法
原因是,使用静态SQL,您可以对更多不同的查询使用相同的语句—这里一个用于具有数据范围的访问,另一个用于不具有数据范围的访问
动态选项为每个访问生成不同的SQL
您可以在以下网站上看到:
具有日期范围的访问
-------------------------------------------------------------------------------
| 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)
这两条语句生成不同的执行计划,该计划针对输入参数进行了优化。在静态选项中,对于可能导致问题的所有输入,use必须共享相同的执行计划。SQL文本是静态的还是您可以基于输入参数生成动态SQL?您可以使用Oracle的内置函数
nvl
,假设未输入的参数值与null
相同。你熟悉这个功能吗?如果DATE\u START
为空,使用另一个Oracle内置函数“to_date”创建一个日期,到目前为止,所有列的值都将比它更新。感谢您的响应@MarmiteBomber是的sql是动态的这些参数是从jasper报告中输入的感谢您的响应@Abra否我不熟悉nvl,最近刚开始使用oracle。在我的例子中,datetrx从来都不是空值,但我可能不输入参数,仍然希望将所有内容与anydate一起提供。现在,如果我不输入date参数,当我使用上述方法时,我会得到一个空白报告。