Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.05.2015, 08:01   #1
ksu04061992
Пользователь
 
Регистрация: 29.11.2011
Сообщений: 23
По умолчанию Поиск в таблице БД

Добрый день, нужна ваша помощь! Нужно организовать поиск в таблице только по тем параметрам, которые выбраны. Если параметр не выбран то его в запросе не учитывать. Примером может служить поиск автомобилей на сайте, где мы выбираем только те параметры которые нам нужны, остальные не учитываем. Как организовывают такие запросы и где об этом можно почитать?
ksu04061992 вне форума Ответить с цитированием
Старый 09.05.2015, 08:20   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Это можно сделать заглушками:
Код:
with Query do begin
 sql.text:='select from таблица where 1=1';
 if Edit1.Text<>'' then sql.append(' and поле1='+Edit1.Text);
 if Edit2.Text<>'' then sql.append(' and поле2='+Edit2.Text);
 if Edit3.Text<>'' then sql.append(' and поле3='+Edit3.Text);
 ...
end;
1=1 тут выступает как заглушка, благодаря которой потом можно условия запроса варьировать подставляя или не подставляя новые.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.05.2015, 08:27   #3
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Обычно динамически формирую строку условий, примерно в этом же духе, и если не пустая, то добавляю к запросу where и сформированную строку. Без всяких 1=1, лишний and слева или справа сформированной строки убрать нет проблем. Обычно проблемы возникают при участии даты/времени, действительных чисел в таких конструкциях, нужно быть по аккуратней, четко понимая чего пишешь и как СУБД поймет
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 09.05.2015 в 08:32.
Аватар вне форума Ответить с цитированием
Старый 09.05.2015, 08:31   #4
xxbesoxx
Участник клуба
 
Регистрация: 10.08.2010
Сообщений: 1,389
По умолчанию

Цитата:
поиск в таблице только по тем параметрам
1) Создайте для тренировке какой то таблица
2) скачайте книга Флёнов М.Е. - Библия Delphi (3-е издание) - 2011.pdf Глава 14. Delphi и база данных и на 405 странице объясняет параметризированный запрос

Последний раз редактировалось xxbesoxx; 09.05.2015 в 08:34.
xxbesoxx вне форума Ответить с цитированием
Старый 09.05.2015, 08:38   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Фленов много чего написал и не всегда нужно его указаниям следовать. Параметризированный запрос хорошо, но не всегда панацея. Как быть, если возможных условий поиска два-три десятка, а уж о числе их комбинаций не прилично говорить. Посмотрю на этот параметризированный запрос, пестрящий заглушками вида 1=1 или чего-то в таком духе, и не всегда это удастся сделать
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 09.05.2015 в 08:41.
Аватар вне форума Ответить с цитированием
Старый 09.05.2015, 09:26   #6
ksu04061992
Пользователь
 
Регистрация: 29.11.2011
Сообщений: 23
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Обычно динамически формирую строку условий, примерно в этом же духе, и если не пустая, то добавляю к запросу where и сформированную строку. Без всяких 1=1, лишний and слева или справа сформированной строки убрать нет проблем. Обычно проблемы возникают при участии даты/времени, действительных чисел в таких конструкциях, нужно быть по аккуратней, четко понимая чего пишешь и как СУБД поймет
А пример есть какой нибудь?
ksu04061992 вне форума Ответить с цитированием
Старый 09.05.2015, 09:55   #7
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Думаешь реальный пример что-то даст? Ну вот выдернул кусочек для примера сколько уместилось
Код:
  s1:=Format('(V.Zona=%d OR (V.Zona=%d AND V.DatOut1>=''%s''))',[gdcZonaIn,gdcZonaOut,xMaxOut]);
  case PS.ByName('FTehn').AsByte of
  1:  s1:=s1+Format(' AND V.Status & %d<>0 AND V.Status & %d=0 AND V.TGruz=%d',[gdcStInSeverE+gdcStInOstat,gdcStAdressB+gdcStToPogruzB,gdcGruzNone]);
  2:  s1:=s1+Format(' AND V.Status & %d<>0 AND V.Status & %d=0 AND V.TGruz=%d',[gdcStInSeverE+gdcStInOstat,gdcStToSeverB+gdcStToRazgruzB,gdcGruzStoron]);
  3:  s1:=s1+Format(' AND V.Status & %d=%d',[gdcStToPogruzE+gdcStPogruzkaB,gdcStToPogruzE]);
  4:  s1:=s1+Format(' AND V.Status & %d=%d',[gdcStToRazgruzE+gdcStRazgruzkaB,gdcStToRazgruzE]);
  5:  s1:=s1+Format(' AND V.Status & %d=%d',[gdcStPogruzkaB+gdcStPogruzkaE,gdcStPogruzkaB]);
  6:  s1:=s1+Format(' AND V.Status & %d=%d',[gdcStRazgruzkaB+gdcStRazgruzkaE,gdcStRazgruzkaB]);
  7:  s1:=s1+Format(' AND V.Status & %d=0 AND V.Status & %d<>0',[gdcStToSeverB,gdcStTTNaklB+gdcStTTNaklGrB]);
  8:  s1:=s1+Format(' AND V.Status & %d=%d',[gdcStOutSeverE+gdcStOutRubegnB,gdcStOutSeverE]);
  9:  s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpRegInRubegn,sdGdcSmenaId]);
  10: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpToPogruz,sdGdcSmenaId]);
  11: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpToRazgruz,sdGdcSmenaId]);
  12: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpPogruzka,sdGdcSmenaId]);
  13: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpRazgruzka,sdGdcSmenaId]);
  14: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpToSever,sdGdcSmenaId]);
  15: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpRegOutRubegn,sdGdcSmenaId]);
  16: s1:=s1+Format(' AND EXISTS(SELECT * FROM GdcVagOper O WHERE O.GdcVag_Id=V.GdcVag_Id AND O.KodOper=%d AND O.GdcSmena_IdBeg=%d)',[gdcOpRegInOstat,sdGdcSmenaId]);
  17: s1:=s1+Format(' AND V.Status & %d=%d',[gdcStPogruzkaE+gdcStOutSeverE,gdcStPogruzkaE]);
  18: s1:=s1+Format(' AND V.Status & %d=0 AND V.Status & %d<>0 AND COALESCE(V.SignUser,0)=0',[gdcStOutSeverE,gdcStTTNaklB+gdcStTTNaklGrB]);
  end;
  case PS.ByName('FSobstv').AsByte of
  1: s1:=s1+Format(' AND V.Sobstv NOT IN (%d,%d)',[gdcSobstvMPS,gdcSobstvStor]);
  2: s1:=s1+Format(' AND V.Sobstv=%d',[gdcSobstvMPS]);
  3: s1:=s1+Format(' AND V.Sobstv=%d',[gdcSobstvStor]);
  4: s1:=s1+Format(' AND V.Sobstv IN (%d,%d)',[gdcSobstvMPS,gdcSobstvStor]);
  end;
  case PS.ByName('FAdmin').AsByte of
  1: s1:=s1+' AND M.Param1=300';
  2: s1:=s1+' AND COALESCE(M.Param1,0)<>300';
  end;
  if PS.ByName('FTipGd').ArrayCount>0 then begin
    s:='';
    for i:=0 to PS.ByName('FTipGd').ArrayCount-1 do s:=s+PS.ByName('FTipGd').ArrayGet(i)+',';
    s:=spLeft(s,Length(s)-1);
    if PS.ByName('FTipGd').ArrayCount=1 then s1:=s1+Format(' AND V.TipGd=%s',[s])
    else if PS.ByName('FTipGd').ArrayCount<20 then s1:=s1+Format(' AND V.TipGd IN (%s)',[s])
    else begin
      if not MListKeys('#GdcVagTipGdTemp',s) then Exit;
      s1:=s1+' AND EXISTS(SELECT * FROM #GdcVagTipGdTemp Q WHERE Q.KeyId=V.TipGd)';
    end;
  end;
  if PS.ByName('FTipPr').ArrayCount>0 then begin
    s:='';
    for i:=0 to PS.ByName('FTipPr').ArrayCount-1 do s:=s+PS.ByName('FTipPr').ArrayGet(i)+',';
    s:=spLeft(s,Length(s)-1);
    if PS.ByName('FTipPr').ArrayCount=1 then s1:=s1+Format(' AND V.TipPr=%s',[s])
    else if PS.ByName('FTipPr').ArrayCount<20 then s1:=s1+Format(' AND V.TipPr IN (%s)',[s])
    else begin
      if not MListKeys('#GdcVagTipPrTemp',s) then Exit;
      s1:=s1+' AND EXISTS(SELECT * FROM #GdcVagTipPrTemp Q WHERE Q.KeyId=V.TipPr)';
    end;
  end;
  case PS.ByName('FRegl').AsByte of
  1: s1:=s1+Format(' AND V.Regl=%d',[gdcReglPogruz]);
  2: s1:=s1+Format(' AND V.Regl=%d',[gdcReglRazgr]);
  3: s1:=s1+Format(' AND V.Regl=%d',[gdcReglProm]);
  4: s1:=s1+Format(' AND V.Regl=%d',[gdcReglNot]);
  5: s1:=s1+Format(' AND V.Regl=%d',[gdcReglRemont]);
  end;
  if PS.ByName('FPKodProd').AsWord3>0 then s1:=s1+Format(' AND V.PKodProd=%d',[PS.ByName('FPKodProd').AsWord3]);
  if PS.ByName('FOKodProd').AsInteger>=0 then begin
    s3:=GdcDM.ListOKodProd(PS.ByName('FOKodProd').AsInteger);
    if GdcDM.CountProd<2 then s1:=s1+Format(' AND V.OKodProd=%d',[PS.ByName('FOKodProd').AsInteger])
                         else s1:=s1+Format(' AND V.OKodProd IN (%s)',[s3]);
  end;
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 09.05.2015, 11:12   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
скачайте книга Флёнов М.Е.
Да. Скачайте чтоб сразу в корзину отправить )))
Цитата:
Как быть, если возможных условий поиска два-три десятка
В таких случаях запросы хорошо упаковывать в хранимые процедуры.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.05.2015, 12:18   #9
xxbesoxx
Участник клуба
 
Регистрация: 10.08.2010
Сообщений: 1,389
По умолчанию

Цитата:
Да. Скачайте чтоб сразу в корзину отправить )))
хорошо , вернемся к делу
Цитата:
поиск в таблице только по тем параметрам, которые выбраны.
пишу параметризованный запрос примерно так
Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
   with ADOQuery1 do
   begin
     SQL.Text := 'Select Код, Naimenovanie, Proizvoditel, kolvo '+
                 ' from tab1  '+
                 ' where Naimenovanie=:pNaimenovanie '+
                 ' and Proizvoditel=:pProizvoditel ';
      Parameters.ParamByName('pNaimenovanie').Value := Trim(edtNaimenovanie.Text);
      Parameters.ParamByName('pProizvoditel').Value := Trim(edtProizvoditel.Text);
     Open;
   end;
end;
У Tab1 ест 2 параметр pNaimenovanie и pProizvoditel работает ! Но здесь еще сказано
Цитата:
Если параметр не выбран то его в запросе не учитывать.
Как это реализовать ? на #2 sql.append я извиняюсь не понял ... как будет на это примере ?

Последний раз редактировалось xxbesoxx; 09.05.2015 в 12:23.
xxbesoxx вне форума Ответить с цитированием
Старый 09.05.2015, 12:32   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
не понял ... как будет на это примере ?
А вот так как я и показал.
Ты заранее определяешь тело запроса, его начало.
1=1 это заглушка, которая позволяет сразу описать условие where в запросе.
При этом запрос по факту эквивалентен обычному select from таблица, поскольку 1=1 заранее даст всегда True.
Однако при такой заглушке ты к строке запроса можешь приписывать однотипные строки условия, впереди которых всегда будет стоять AND или OR, и это не нарушит синтаксиса, поскольку и слово where уже есть, и первый AND не нужно убирать из-за заглушки.

Если бы не было заглушки то как сказал Аватар пришлось бы вычислять, были ли к запросу дописаны уже какие-то условия. Если были - писать AND если не были - не писать. Заглушка то все равно самой СУБД оптимизируется как правило, и не влияет на отбор, так что не мешает.
А Append() это просто метод, добавляющий к списку запроса еще одну строку.
Можно было написать sql.text:=sql.text+... Ну я вот Append() захотел.

Попробуй в уме прокрутить запрос такой, как его строка будет меняться в зависимости от введенного в Эдиты, и ты поймешь в чем состоит роль заглушки.
Т.е. заглушка призвана беречь запрос от нарушения синтаксиса SQL команды вне зависимости от того что ты там дальше по ходу программы будешь к запросу пририсовывать.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
поиск id в таблице tanek Помощь студентам 7 11.03.2012 16:29
поиск по таблице sid1868 Помощь студентам 1 10.11.2010 16:23
Поиск по таблице Kemeron Microsoft Office Access 1 02.06.2010 21:55
Поиск в таблице k1r1ch Общие вопросы Delphi 1 30.06.2009 15:57
Поиск в таблице Voffka БД в Delphi 1 08.05.2007 01:16