Jedną z metod byłoby użycie wariantu
WHERE column = nvl(var, column)
Istnieją jednak dwie pułapki:
-
jeśli kolumna dopuszcza wartość null, ta klauzula będzie filtrować wartości null, podczas gdy w twoim pytaniu nie filtrujesz wartości null w drugim przypadku. Możesz zmodyfikować tę klauzulę, aby uwzględnić wartości null, ale okazuje się to brzydkie:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Oczywiście, jeśli jakoś
impossible_value
zostanie włożony, napotkasz inne (zabawne) problemy. - Optymalizator nie rozumie poprawnie tego typu klauzuli. Czasami tworzy plan z UNION ALL, ale jeśli jest więcej niż kilka
nvl
, uzyskasz pełne skanowanie, nawet jeśli obecne są doskonale poprawne indeksy.
Dlatego, gdy istnieje wiele parametrów (na przykład kilka pól wyszukiwania w dużym formularzu), lubię używać dynamicznego SQL:
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;
Możesz także użyć EXECUTE IMMEDIATE l_query INTO l_result USING param1;