У меня есть SQL с параметрами, переданными пользователем. Пользователь может передать какой-нибудь идентификатор или -1, что означает «неважно». Можно написать запрос, как показано ниже, но можно ли использовать индекс?
SELECT *
FROM table
WHERE
((col1 = :param1) OR (:param1 = -1))
AND ((col2 = :param2) OR (:param2 = -1))
AND col3 STARTING 'A'
col1
, col2
и col3
проиндексированы. В FB 2.x с использованием OR
никогда не используйте index для col1 или col2. В FB 3, только если существуют первые (или вторые) условия, которые могут использовать индекс (индекс PLAN и естественный), но с последним условием прекращают использование индекса для col1 / 2.
Как я могу написать SQL без использования PLAN и могу использовать индекс для col1/2
и оставить возможность «выключить» состояние, передав -1
?
SQL пишется в интерфейсе (а не в коде) и должен быть универсальным. Что-то вроде IBExpert, но SQL написал один раз (например, суперпользователем) и не будет менять при каждом использовании с разными параметрами.
Вариантом может быть включение логики в EXECUTE BLOCK
...
@ Dżyszla. . . Создайте предложение where
динамически и добавьте его в запрос. Условия с or
намного сложнее оптимизировать, чем условия только с and
.
предоставить суперпользователю возможность предоставлять варианты частей sql. Или конструктор как в IBExpert
Нет, нет ... Суперпользователь создает какой-то запрос. Сборка приложения для этого (на основе параметров запроса) интерфейса, использующего "обычного" пользователя. Один раз суперпользовательский запрос на запись и хочет дать другим возможность указать (> 0) или нет (-1) фильтр. Поэтому необходимо создать запрос для обоих случаев.
Таким образом, приложение должно иметь возможность брать от суперпользователя не фиксированный один раз для всех запросов, а шаблон, из которого могут быть построены слегка изменяющиеся запросы.
PS AFAIR можно явно указать план выполнения в операторе SQL, но тогда не будет никакой гарантии, что пользовательский план будет оптимальным или правильным. В конце концов, вы производите сортировку по столбцам три, неясно, что объединение индексов №1 и №2, а затем сканирование nat по col3 всегда будет лучше, чем сначала сокращение на col3, а затем nat-сканирование по col1 и col2
Вы можете переписать условие вроде
(col1 = :param1) OR (:param1 = -1)
в виде
col1 = case when :param1 = -1 then col1 else :param1 end
Поскольку это одно выражение, вы также можете безопасно удалить все скобки, что упростит чтение запроса.
Еще ПЛАНИРУЙТЕ (НАТУРАЛЬНО) и прочтите все записи - это не работает в Firebird :(
Я не думаю, что выражение case
уменьшит вероятность использования индекса увеличивать.
почему бы не построить другой SQL для запроса на клиенте (или даже в SP) на основе параметров фильтра?