![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Переменное число параметров запроса [D7, IB 7.1]
Lavrenty © (2007-06-09 15:57:00)Здравствуйте мастера! Подскажите пожалуйста как составить запрос с переменным числом параметров, так как параметрами запроса Q1 являются значения поля f_id запроса Q2 из другой базы. Т. е. количество записей в Q2 заранее неизвестно, ну а так как запросы из разных баз, то конструкции типа whereили joinне подходят (IB7.1, компоненты IBExpress).
Грициан (2007-06-19 13:25:00) [1]Global temporary tables
временные таблицы
Lavrenty (2007-06-18 22:23:00) [2]
> Грициан (18.06.07 15:07) [16]
> Ну дык, раз IB 7+, то есть GTT, заполняй и джойнь.
прошу прощения, что такое GTT? В справке не нашёл.
Грициан (2007-06-18 15:07:00) [3]Ну дык, раз IB 7+, то есть GTT, заполняй и джойнь. Или жди IB 8/FB 3, там (возможно) будут полноценные гетерогенные запросы
mysql (2007-06-18 13:20:00) [4]
> Lavrenty © (13.06.07 15:32) [9]
>
> > Sergey13 © (13.06.07 09:04) [8]
> > Можно еще и так ... where f_id in ( select f_id from table_2
> where ...)
>
> Эх, да я бы с радостью, только table_2 в другой базе
вроде так можно:
имя_базы.имя_табл
Megabyte (2007-06-15 13:04:00) [5]Нашел решение:
iif(:brand_name <> '', b.brand_list_title, 0) =
iif(:brand_name <> '', :brand_name, 0)
Если параметр пустой, то тождество 0=0.
Megabyte (2007-06-15 11:26:00) [6]Пробовал даже в IBExperte:
select count(r.repair_id)
from repairs r join phone_model p on r.phone_model_id = p.phone_model_id
join brand_list b on p.brand_list_id = b.brand_list_id
join territory t on r.terr_id = t.territory_id
where (CAST(r.reception_date as date) between '01.05.2007' and '31.05.2007') and
(r.check_warranty = 0) and (r.repair_type_id <> 2000) and
(t.territory_title in ('??????????, ??????? ??????'))
and (b.brand_list_title in (
select bl.brand_list_title
from brand_list bl) )
and (r.is_person = 1)
Так работает.
select count(r.repair_id)
from repairs r join phone_model p on r.phone_model_id = p.phone_model_id
join brand_list b on p.brand_list_id = b.brand_list_id
join territory t on r.terr_id = t.territory_id
where (CAST(r.reception_date as date) between '01.05.2007' and '31.05.2007') and
(r.check_warranty = 0) and (r.repair_type_id <> 2000) and
(t.territory_title in ('??????????, ??????? ??????'))
and (b.brand_list_title in (:brand) )
and (r.is_person = 1)
где параметр = select bl.brand_list_title
from brand_list bl
Не работает, выдает 0. :(
Конечно можно тупо запросы формировать на клиенте, но хотелось бы автоматизировать через ХП!
megabyte (2007-06-14 16:03:00) [7]Дабы не плодить тему. Интересует переменное количество параметров в ХП.
Если какой-то параметр запроса не выбран, то выводить по всем.
Одна из ХП:
CREATE PROCEDURE WARRANT_ON_PERIOD (
begin_date date,
end_date date,
terr varchar(48),
is_person smallint,
brand_name varchar(48),
client_name varchar(48))
returns (
kolvo smallint)
as
begin
if (:is_person = 0) then /*??? ????????????? ????????*/
begin
select count(r.repair_id)
from repairs r join phone_model p on r.phone_model_id = p.phone_model_id
join brand_list b on p.brand_list_id = b.brand_list_id
join territory t on r.terr_id = t.territory_id
join corporate_client c on r.corporate_client_id = c.corporate_client_id
where (CAST(r.reception_date as date) between :begin_date and :end_date) and
(r.check_warranty = 0) and (r.repair_type_id <> 2000) and
(t.territory_title in (:terr))
and (b.brand_list_title in (:brand_name))
and (c.corporate_client_title in (:client_name))
into
:kolvo;
suspend;
end
else /*??? ??????? ????????*/
begin
select count(r.repair_id)
from repairs r join phone_model p on r.phone_model_id = p.phone_model_id
join brand_list b on p.brand_list_id = b.brand_list_id
join territory t on r.terr_id = t.territory_id
where (CAST(r.reception_date as date) between :begin_date and :end_date) and
(r.check_warranty = 0) and (r.repair_type_id <> 2000) and
(t.territory_title in (:terr)) and (b.brand_list_title in (:brand_name))
and (r.is_person = 1)
into
:kolvo;
suspend;
end
end
Делаю так, если параметр процедуры на клиенте пустой, то в параметр запроса ХП пишу:
if (abrand = '') then
fdst_operat.ParamByName('BRAND_NAME').AsString:= DstToStr(fdst_brand)
else
fdst_operat.ParamByName('BRAND_NAME').AsString := abrand;
DstToStr(fdst_brand) - процедура формирования строки с разделителями(всех брендов) на основе справочного НД.
Ругается, говорит что arithmetic exception, numeric overflow or string truncetion...
Но это еще не все. Ввел просто в параметр вручную несколько Брендов('Nokia', 'Samsung'), запрос выдает не сумму, а нули, т.е. это воспринимается как один бренд.
Пробовал применить еще такую конструкцию:
...(b.brand_list_title = (iif(:brand_name is not null, :brand_name, any(
select bl.brand_list_title
from brand_list bl)) ))
Ругается на any, т.е. как-будто в iif можно только единичное значение вводить.
Как мне сделать?
Не хочется делать кучу if в ХП. Других вариантов не вижу пока...
Lavrenty (2007-06-13 15:41:00) [8]> [10] Sergey13 © (13.06.07 15:35)
А вот этого я не знаю. Пойду рыть доку.
Спасибо всем!
Sergey13 (2007-06-13 15:35:00) [9]> [9] Lavrenty © (13.06.07 15:32)
Через внешние таблицы можно попробовать, если они есть в ИБ7.
Lavrenty (2007-06-13 15:32:00) [10]
> Sergey13 © (13.06.07 09:04) [8]
> Можно еще и так ... where f_id in ( select f_id from table_2 where ...)
Эх, да я бы с радостью, только table_2 в другой базе
Sergey13 (2007-06-13 09:04:00) [11]> [2] Lavrenty © (09.06.07 16:05)
> Насколько знаю IN применяется так
> ... where f_id in ( x1, x2, x3)
Ты не все знаешь. Можно еще и так
... where f_id in ( select f_id from table_2 where ...)
Sergey Masloff (2007-06-11 09:50:00) [12]Гетерогенные запросы маст дай. Если данные обрабатываются совместно - они должны быть в одной (физически и логически) базе. Если IB не позволяет логически объединить две базы - то нужно делать копию данных.
Все остальное (в 90 % случаев) - костыли и грабли
Lavrenty (2007-06-10 18:19:00) [13]
> S@shka © (09.06.07 17:14) [5]
> Интересно как ты хочешь запихать, если сам не знаешь что
> может быть.
Что вопрос заново повторить ?
> Я не вижу тут 40 строк.
Неужели непонятно, что строки формирования запроса приведены непоностью?
А вообще, нельзя ли по существу?
S@shka (2007-06-09 17:14:00) [14]Интересно как ты хочешь запихать, если сам не знаешь что может быть.
Я не вижу тут 40 строк.
Lavrenty (2007-06-09 17:08:00) [15]
> S@shka © (09.06.07 16:52) [3]
> Создавать второй запрос после первого через SQL.TEXT :=
Вообще-то я примерно так и делаю
IBQ.SQL.ADD('select');
IBQ.SQL.ADD(' field1');
IBQ.SQL.ADD('where f_id in(');
и т.д. всего около 40 строк. Далее по циклу выуживаю значения f_id
while not (IBQ2.Eof) do begin
IBQ.SQL.Add(IBQ2l.FieldByName('f_id').AsString);
IBQ2.Next;
if not IBQ2.Eof then
IBQ.SQL.Add(' ,');
end;
IBQ.SQL.ADD(')');
IBQ.Open;
Но всё это некрасиво и занимает много места в тескте проги. Куда лучше запихать текст запроса в компонент при конструировании, и подставлять туда лишь только параметры. Вот только как?
S@shka (2007-06-09 16:52:00) [16]Создавать второй запрос после первого через
SQL.TEXT :=
Lavrenty (2007-06-09 16:05:00) [17]Насколько знаю IN применяется так
... where f_id in ( x1, x2, x3)
но для этого надо знать заранее сколько этих иксов. Вот как EXIST пользоваться не знаю, надо прочитать.
Sergey13 (2007-06-09 15:58:00) [18]> [0] Lavrenty © (09.06.07 15:57)
Есть еще IN в запросах для этого. Или EXISTS.