В настоящее время у меня есть подготовленный оператор в Java, который использует следующий оператор SQL в предложении WHERE моего запроса, но я хотел бы переписать это в функцию, чтобы ограничить передаваемые ей параметры пользователя и, возможно, сделать его эффективный.
(
(USER_PARAM2 IS NULL AND
( COLUMN_NAME = nvl(USER_PARAM1, COLUMN_NAME) OR
(nvl(USER_PARAM1, COLUMN_NAME) IS NULL)
)
)
OR
(USER_PARAM2 IS NOT NULL AND COLUMN_NAME IS NULL)
)
USER_PARAM1 и USER_PARAM2 передаются в подготовленный оператор пользователем.
USER_PARAM1 представляет то, что пользователь приложения хочет найти в данном конкретном COLUMN_NAME. Если пользователь не включает этот параметр, он по умолчанию будет иметь значение NULL.
USER_PARAM2 был моим способом разрешить пользователю запрашивать поиск только по значению NULL в этом COLUMN_NAME. Кроме того, у меня есть некоторая серверная логика, которая устанавливает для USER_PARAM2 значение «true», если оно передано пользователем, или значение NULL, если оно не было указано пользователем.
Предполагаемое поведение заключается в том, что если было объявлено USER_PARAM2, то возвращаются только значения COLUMN_NAME со значением NULL. Если USER_PARAM2 не был объявлен, а USER_PARAM1 был объявлен, то возвращается только COLUMN_NAME = USER_PARAM1. Если ни один пользовательский параметр не объявлен, возвращаются все строки.
Может ли кто-нибудь помочь мне в этом?
Заранее спасибо ...
EDIT:
Просто чтобы уточнить, как выглядит мой текущий запрос (без других операторов предложения WHERE ..)
SELECT *
FROM TABLE_NAME
WHERE (
(USER_PARAM2 IS NULL AND
( COLUMN_NAME = nvl(USER_PARAM1, COLUMN_NAME) OR
(nvl(USER_PARAM1, COLUMN_NAME) IS NULL)
)
)
OR
(USER_PARAM2 IS NOT NULL AND COLUMN_NAME IS NULL)
)
... и я бы хотел попасть туда ...
SELECT *
FROM TABLE_NAME
WHERE customSearchFunction(USER_PARAM1, USER_PARAM2, COLUMN_NAME)
РЕДАКТИРОВАТЬ # 2:
Итак, другой сотрудник помог мне с этим ...
CREATE OR REPLACE function searchNumber (pVal IN NUMBER, onlySearchForNull IN CHAR, column_value IN NUMBER)
RETURN NUMBER
IS
BEGIN
IF onlySearchForNull IS NULL THEN
IF pVal IS NULL THEN
RETURN 1;
ELSE
IF pVal = column_value THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END IF;
ELSE
IF column_value IS NULL THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END IF;
END;
... это похоже на мои первые испытания ..
SELECT *
FROM TABLE_NAME
WHERE 1=searchNumber(USER_PARAM1, USER_PARAM2, COLUMN_NAME);
... единственные проблемы, которые у меня были с этим, были бы
1) возможные проблемы производительности по сравнению со сложным оператором SQL, с которого я начал.
2) что мне придется создавать аналогичные функции для каждого типа данных.
Тем не менее, последнее будет менее важным для меня.
РЕДАКТИРОВАТЬ # 3 2012.02.01
Итак, мы остановились на решении, которое я выбрал ниже, при использовании подхода, основанного на функциях, где чистота кода / запроса повышает производительность. Мы обнаружили, что подход, основанный на функциях, работает примерно в 6 раз хуже, чем при использовании чистого SQL.
Спасибо всем за отличный вклад!
РЕДАКТИРОВАТЬ # 4 2012.02.14
Итак, оглядываясь назад, я заметил, что применение концепции виртуальной таблицы в решении @ Alan с ясностью решения @ danihp дает очень хорошее общее решение с точки зрения ясности и производительности. Вот что у меня сейчас
WITH params AS (SELECT user_param1 AS param, user_param2 AS param_nullsOnly FROM DUAL)
SELECT *
FROM table_name, params p
WHERE ( nvl(p.param_nullsOnly, p.param) IS NULL --1)
OR p.param_nullsOnly IS NOT NULL AND column_name IS NULL --2)
OR p.param IS NOT NULL AND column_name = p.param --3)
)
-- 1) Test if all rows should be returned
-- 2) Test if only NULL values should be returned
-- 3) Test if param equals the column value
Еще раз спасибо за предложения и комментарии!