Форум: "Базы";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];
ВнизПеременное число параметров запроса Найти похожие ветки
← →
Lavrenty © (2007-06-09 15:57) [0]Здравствуйте мастера! Подскажите пожалуйста как составить запрос с переменным числом параметров, так как параметрами запроса Q1 являются значения поля f_id запроса Q2 из другой базы. Т. е. количество записей в Q2 заранее неизвестно, ну а так как запросы из разных баз, то конструкции типа where или join не подходят (IB7.1, компоненты IBExpress).
← →
Sergey13 © (2007-06-09 15:58) [1]> [0] Lavrenty © (09.06.07 15:57)
Есть еще IN в запросах для этого. Или EXISTS.
← →
Lavrenty © (2007-06-09 16:05) [2]Насколько знаю IN применяется так
... where f_id in ( x1, x2, x3)
но для этого надо знать заранее сколько этих иксов. Вот как EXIST пользоваться не знаю, надо прочитать.
← →
S@shka © (2007-06-09 16:52) [3]Создавать второй запрос после первого через
SQL.TEXT :=
← →
Lavrenty © (2007-06-09 17:08) [4]
> 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 17:14) [5]Интересно как ты хочешь запихать, если сам не знаешь что может быть.
Я не вижу тут 40 строк.
← →
Lavrenty © (2007-06-10 18:19) [6]
> S@shka © (09.06.07 17:14) [5]
> Интересно как ты хочешь запихать, если сам не знаешь что
> может быть.
Что вопрос заново повторить ?
> Я не вижу тут 40 строк.
Неужели непонятно, что строки формирования запроса приведены непоностью?
А вообще, нельзя ли по существу?
← →
Sergey Masloff (2007-06-11 09:50) [7]Гетерогенные запросы маст дай. Если данные обрабатываются совместно - они должны быть в одной (физически и логически) базе. Если IB не позволяет логически объединить две базы - то нужно делать копию данных.
Все остальное (в 90 % случаев) - костыли и грабли
← →
Sergey13 © (2007-06-13 09:04) [8]> [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 ...)
← →
Lavrenty © (2007-06-13 15:32) [9]
> Sergey13 © (13.06.07 09:04) [8]
> Можно еще и так ... where f_id in ( select f_id from table_2 where ...)
Эх, да я бы с радостью, только table_2 в другой базе
← →
Sergey13 © (2007-06-13 15:35) [10]> [9] Lavrenty © (13.06.07 15:32)
Через внешние таблицы можно попробовать, если они есть в ИБ7.
← →
Lavrenty © (2007-06-13 15:41) [11]> [10] Sergey13 © (13.06.07 15:35)
А вот этого я не знаю. Пойду рыть доку.
Спасибо всем!
← →
megabyte © (2007-06-14 16:03) [12]Дабы не плодить тему. Интересует переменное количество параметров в ХП.
Если какой-то параметр запроса не выбран, то выводить по всем.
Одна из ХП: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 в ХП. Других вариантов не вижу пока...
← →
Megabyte © (2007-06-15 11:26) [13]Пробовал даже в 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-15 13:04) [14]Нашел решение:
iif(:brand_name <> "", b.brand_list_title, 0) =
iif(:brand_name <> "", :brand_name, 0)
Если параметр пустой, то тождество 0=0.
← →
mysql (2007-06-18 13:20) [15]
> 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 в другой базе
вроде так можно:
имя_базы.имя_табл
← →
Грициан (2007-06-18 15:07) [16]Ну дык, раз IB 7+, то есть GTT, заполняй и джойнь. Или жди IB 8/FB 3, там (возможно) будут полноценные гетерогенные запросы
← →
Lavrenty © (2007-06-18 22:23) [17]
> Грициан (18.06.07 15:07) [16]
> Ну дык, раз IB 7+, то есть GTT, заполняй и джойнь.
прошу прощения, что такое GTT? В справке не нашёл.
← →
Грициан (2007-06-19 13:25) [18]Global temporary tables
временные таблицы
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.049 c