Oracle 未输入参数时,忽略where子句中的日期范围参数

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

未输入参数时,忽略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 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参数,当我使用上述方法时,我会得到一个空白报告。