Une méthode serait d'utiliser une variante de
WHERE column = nvl(var, column)
Il y a cependant deux écueils :
-
si la colonne est nullable, cette clause filtrera les valeurs nulles alors que dans votre question, vous ne filtreriez pas les valeurs nulles dans le second cas. Vous pourriez modifier cette clause pour prendre en compte les valeurs nulles, mais cela devient moche :
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Bien sûr, si d'une manière ou d'une autre la
impossible_value
est jamais inséré, vous rencontrerez d'autres types de problèmes (amusants). - L'optimiseur ne comprend pas correctement ce type de clause. Il produira parfois un plan avec un UNION ALL mais s'il y a plus d'un couple de
nvl
, vous obtiendrez une analyse complète même si des index parfaitement valides sont présents.
C'est pourquoi lorsqu'il y a beaucoup de paramètres (plusieurs champs de recherche dans un grand formulaire par exemple), j'aime utiliser le SQL dynamique :
DECLARE
l_query VARCHAR2(32767) := 'SELECT ... JOIN ... WHERE 1 = 1';
BEGIN
IF param1 IS NOT NULL THEN
l_query := l_query || ' AND column1 = :p1';
ELSE
l_query := l_query || ' AND :p1 IS NULL';
END IF;
/* repeat for each parameter */
...
/* open the cursor dynamically */
OPEN your_ref_cursor FOR l_query USING param1 /*,param2...*/;
END;
Vous pouvez également utiliser EXECUTE IMMEDIATE l_query INTO l_result USING param1;