Você tem duas possibilidades para abordar os parâmetros de entrada opcionais.
O mais simples maneira é usar SQL estático e fornecer default valor para os parâmetros ausentes, para que você obtenha todas as correspondências.
Aqui você simplesmente define os limites para a DATE mínima e máxima possível.
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')
Quanto mais avançado way foi popularizado por Tom Kyte e é baseado no uso de SQL dinâmico.
Se os parâmetros forem fornecidos , você gera SQL normal com o
BETWEEN
predicado :select *
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between $P{DATE_START} and $P{DATE_END}
Caso o parâmetro esteja faltando (ou seja,
NULL
é passado) você gera um SQL diferente como mostrado abaixo. select *
from customer
where customer_id = $P{CLIENT_ID}
and (1=1 or datetrx between $P{DATE_START} and $P{DATE_END})
Observe que
1) o número de variáveis de ligação é o mesmo em ambas as variantes da consulta, o que é importante, pois você pode usar
setXXXX
idêntico declarações 2) devido ao atalho
1 = 1 or
é o between
predicado ignorado, ou seja, todas as datas são consideradas. Qual opção deve ser usada?
Bem, para consultas simples, haverá uma pequena diferença, mas para consultas complexas com várias opções de parâmetros ausentes e dados grandes, a abordagem SQL dinâmica é preferida .
A razão é que, usando SQL estático, você usa a mesma instrução para consultas mais diferentes - aqui uma para acesso com intervalo de dados e um para acesso sem intervalo de dados.
A opção dinâmica produz SQL diferente para cada acesso.
Você pode vê-lo nos planos de execução:
Acesso com intervalo de datas
-------------------------------------------------------------------------------
| 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)
Acesso sem intervalo de dados
------------------------------------------------------------------------------
| 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)
Ambas as instruções produzem um plano de execução diferente, que é otimizado para o parâmetro de entrada. Na opção estática, o uso deve compartilhar o mesmo plano de execução para todas as entradas que possam causar problemas.