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

时间:2019-06-26 14:58:38

标签: oracle

如果不输入参数,则忽略where子句中的日期范围参数。对于我的日期范围即时通讯使用之间。

这些参数是从jasper报告中输入的

functionA

如果未输入日期,则报告应携带任何日期的记录,因为未输入日期范围

1 个答案:

答案 0 :(得分:0)

您有两种方法来处理可选的输入参数。

简单方法是使用静态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)由于快捷方式 1 = 1 or被忽略了between谓词,即考虑了所有日期。

应使用哪个选项?

对于简单查询而言,差异很小,但是对于具有缺失参数和大数据的几种选择的复杂查询,首选动态SQL方法

原因是,使用静态SQL时,同一条语句用于更多不同的查询-这里一个用于访问 数据范围,而另一个用于访问数据范围。

dynamic选项为每次访问生成不同的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)

两个语句都产生不同的执行计划,该计划针对输入参数进行了优化。在静态选项中,必须对所有可能引起问题的输入共享相同的执行计划