Oracle
 sql >> Database >  >> RDS >> Oracle

Ignora il parametro dell'intervallo di date nella clausola where quando il parametro non è inserito

Hai due possibilità per avvicinarti ai parametri di input opzionali.

Il più semplice il modo è utilizzare SQL statico e fornire predefinito valore per i parametri mancanti, in modo da ottenere tutte le corrispondenze.

Qui puoi semplicemente impostare i limiti alla DATA minima e massima possibile.

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')

Più sono avanzati way è stato reso popolare da Tom Kyte e si basa sull'utilizzo di SQL dinamico.

Se i parametri sono forniti , generi SQL normale con il BETWEEN predicato :

select * 
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between $P{DATE_START} and $P{DATE_END}

Nel caso in cui il parametro manchi (cioè NULL è passato) generi un SQL diverso come mostrato di seguito.

select * 
from customer
where customer_id = $P{CLIENT_ID}
and (1=1 or datetrx between $P{DATE_START} and $P{DATE_END})

Nota che

1) il numero delle variabili di collegamento è lo stesso in entrambe le varianti della query, il che è importante in quanto puoi utilizzare setXXXX identico dichiarazioni

2) a causa della scorciatoia 1 = 1 or è il between predicato ignorato, ovvero tutte le date vengono considerate.

Quale opzione dovrebbe essere utilizzata?

Bene, per query semplici ci saranno piccole differenze, ma per query complesse con diverse opzioni di parametri mancanti e dati di grandi dimensioni, è preferibile l'approccio SQL dinamico .

Il motivo è che usando l'SQL statico si usa la stessa istruzione per query più diverse - qui una per l'accesso con intervallo di dati e uno per l'accesso senza intervallo di dati.

L'opzione dinamica produce SQL diverso per ogni accesso.

Potresti vederlo sui piani di esecuzione:

Accesso con intervallo di date

-------------------------------------------------------------------------------
| 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)

Accesso senza intervallo di dati

------------------------------------------------------------------------------
| 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)

Entrambe le istruzioni producono un piano di esecuzione diverso, che è ottimizzato per il parametro di input. Nell'opzione statica l'utilizzo deve condividere lo stesso piano di esecuzione per tutti gli input che potrebbero causare problemi.