-
Добрый день.
На досуге начал оптимизировать свои запросы, и столкнулся с неприятным поведением Firebird :(
Задача передать параметр в запрос, и если параметр определенного значения, скажем -1 то выбирать все строки.
Например:
SELECT *
FROM WARE W
WHERE ((W.id_ware = :param) OR (:param = -1))
Но при этом индекс по id_ware как оказалось не используется :( Вобщем нашел причину тормозов в своих процедурах. Это только маленький пример, запросы с подобными параметрами использую в в процедурах с большим телом в for select
Нашел пока 2 варианта решения, но все они кривые:
1. разбить на два запроса проверив сначала параметр, но при этом надо будет и дублировать и вычисления для каждого запроса :(
т.е
2. в данной процедуре сначала сформировать в переменную запрос в зависимости от параметра и запихнуть его в execute statement, при этом не придется дублировать вычисления, но выглядеть это будет криво.
3. создать для запроса отдельную процедуру и в проуедуре вычислений доставть данные из неё, но данные вариант имеет два минуса: лишняя процедура, дублирование во второй процедуре тела запроса.
Кто-нибудь сталкивался с подобными задачами? Помогите, пожалуста найти более прямой вариант. Если надо могу описать задачу подробнее. -
Как вариант
SELECT *
FROM WARE W
WHERE W.id_ware between :param and :param1
если надо все то от -1 до бесконечности, если одно значения - параметры равны -
Sergey13, Гениально! И главное просто и красиво! Респект и уважуха!!!
Набросил примерчик всё работает отлично
CREATE PROCEDURE SP_TESTIK (param INTEGER)
AS
DECLARE VARIABLE MaxInt INTEGER;
DECLARE VARIABLE param2 INTEGER;
BEGIN
MaxInt = 2147483647; -- (2^32)-1
IF (param IS NULL) THEN param = -1000;
IF (param = -1000) THEN param2 = MaxInt; ELSE param2 = param;
FOR
SELECT W.id_ware
FROM WARE W
WHERE W.id_ware BETWEEN :param AND :param2
INTO :id_ware
DO
BEGIN
-- тыры пыры
-- спасибо Сергею :)
END
END -
> Но при этом индекс по id_ware как оказалось не используется
причина может быть в одноименных параметрах... только в BDE насколько помню так было можно. в ADO же (и др.) одноименные не определяются по имени оба, а только один, т.е. может не использоваться id_ware а может и не сработать сравнение с -1, смотря как парсер определяющий параметры работает.
т.е. 4 вариант - проверить с разноименными, задавать 2 значения, и не попадаться больше на эту удочку. -
sniknik, с одноименнными параметрами действительно были проблемы когда работал с BDE, использовал отдельный "need_all=(1,0)", но те времена прошли
здесь как оказалось проблема в самой СУБД
например запросыSELECT * FROM TABLE T WHERE T.id = :param
- индекс используетсяSELECT * FROM TABLE T WHERE (T.id = :param) OR (1=0)
- индекс не используется, идет чтение всех строк :(SELECT * FROM TABLE T WHERE 1=0
- и в этом запросе индекс не используется, идет чтение всех строк, хотя по условию можно было бы файрбёрду догадаться что таблицу то и проверять ненадо -
sniknik © (03.11.10 12:58) [3]
Да это вопрос СУБД.MSSQL так же работает. -
Кщд (08.11.10 07:38) [6]>Lexer © (03.11.10 11:16)
>На досуге начал оптимизировать свои запросы, и столкнулся с неприятным >поведением Firebird :(
вполне предсказуемое поведение оптимизатора
если переписать через union?