Un método sería usar una variante de
WHERE column = nvl(var, column)
Sin embargo, aquí hay dos trampas:
-
si la columna admite valores nulos, esta cláusula filtrará los valores nulos, mientras que en su pregunta no filtraría los valores nulos en el segundo caso. Podría modificar esta cláusula para tener en cuenta los valores nulos, pero se vuelve feo:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Por supuesto, si de alguna manera el
impossible_value
alguna vez se inserta, se encontrará con otro tipo de problemas (divertidos). - El optimizador no entiende correctamente este tipo de cláusula. A veces producirá un plan con UNION ALL pero si hay más de un par de
nvl
, obtendrá un análisis completo incluso si hay índices perfectamente válidos.
Es por eso que cuando hay muchos parámetros (varios campos de búsqueda en un formulario grande, por ejemplo), me gusta usar SQL dinámico:
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;
También puede usar EXECUTE IMMEDIATE l_query INTO l_result USING param1;