Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Переменное число параметров запроса [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.


Наверх

Титульная страница Поиск, карта сайта Написать письмо