Oracle
 sql >> Base de données >  >> RDS >> Oracle

Ignorer le paramètre de plage de dates dans la clause where lorsque le paramètre n'est pas entré

Vous avez deux possibilités pour aborder les paramètres d'entrée optionnels.

Le plus simple est d'utiliser du SQL statique et de fournir par défaut valeur pour les paramètres manquants, afin que vous obteniez toutes les correspondances.

Ici, vous définissez simplement les limites à la DATE minimale et maximale possible.

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

Le plus avancé a été popularisé par Tom Kyte et est basé sur l'utilisation de SQL dynamique.

Si les paramètres sont fournis , vous générez du SQL normal avec le BETWEEN prédicat :

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

Dans le cas où le paramètre manque (c'est-à-dire NULL est passé) vous générez un SQL différent comme indiqué ci-dessous.

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

Notez que

1) le nombre de variables de liaison est le même dans les deux variantes de la requête, ce qui est important car vous pouvez utiliser des setXXXX identiques déclarations

2) à cause du raccourci 1 = 1 or est le between prédicat ignoré, c'est-à-dire que toutes les dates sont prises en compte.

Quelle option doit être utilisée ?

Eh bien, pour les requêtes simples, il y aura une petite différence, mais pour les requêtes complexes avec plusieurs options de paramètres manquants et de données volumineuses, l'approche SQL dynamique est préférée .

La raison en est qu'en utilisant le SQL statique, vous utilisez la même instruction pour plusieurs requêtes différentes - ici une pour l'accès avec plage de données et une pour l'accès sans plage de données.

L'option dynamique produit un SQL différent pour chaque accès.

Vous pouvez le voir sur les plans d'exécution :

Accès avec plage de dates

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

Accès sans plage de données

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

Les deux instructions produisent un plan d'exécution différent, optimisé pour le paramètre d'entrée. Dans l'option statique, l'utilisation doit partager le même plan d'exécution pour toutes les entrées qui peuvent causer des problèmes.