Один из методов заключается в использовании варианта
WHERE column = nvl(var, column)
Однако здесь есть два подводных камня:
, если столбец обнуляем, этот пункт отфильтруетпустые значения, тогда как в вашем вопросе вы не будете фильтровать нулевые значения во втором случае.Вы можете изменить это предложение так, чтобы оно принимало во внимание значения NULL, но это выглядит ужасно:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Конечно, если когда-нибудь будет вставлен impossible_value
, вы столкнетесь с некоторыми другими (забавными) проблемами.*
- Оптимизатор неправильно понимает этот тип предложения.Иногда он создает план с UNION ALL, но если их больше, чем пара
nvl
, вы получите полное сканирование, даже если присутствуют совершенно правильные индексы.
Вот почему, когда естьЕсть много параметров (например, несколько полей поиска в большой форме), мне нравится использовать динамический 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;
Вы также можете использовать EXECUTE IMMEDIATE l_query INTO l_result USING param1;