Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [InterBase] Поисковый запрос с параметрами, Реализация уточняющего поиска 
V
    Опции темы
Gamber
Дата 21.10.2008, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 24.3.2008

Репутация: нет
Всего: нет



Цитата(Deniz @ 21.10.2008,  13:34)
Цитата(Frees @  21.10.2008,  15:12 Найти цитируемый пост)
 IBQSearchByName.SQL.Add(' AND books.name_book = '#39+fmSearchQuery.edValue.Text+#39);
вот такое категорически не надо делать.
Цитата(Gamber @  21.10.2008,  15:44 Найти цитируемый пост)
ВСЕ! Вроде бы заработало
введи в поле поиска по книге одинарную кавычку

Ага, понял...
Ну вроде бы все исправил, вот посмотрите пожалуйста, надеюсь окончательный код, на предмет ляпов:

Код

procedure TdmBase.aExecuteSearchQueryExecute(Sender: TObject);
var
 incorr_year: boolean;
 incorr_price: boolean;
 terminate: boolean;
begin
     terminate := false;
     incorr_year := false;
     incorr_price := false;
     IBQSearch.Close;
     IBQSearch.SQL.Clear;
     IBQSearch.SQL.text := 'SELECT name_book, name_avt, name_izd, name_firm, god_izd, price_book FROM books, authors, publishes, firms  WHERE ' + ' authors.kod_avt = books.kod_avt AND '+ ' publishes.kod_izd = books.kod_izd AND ' + ' firms.kod_firm = books.kod_firm ';
     if fmSearchQuery.edBook.Text <> '' then
        begin
           IBQSearch.SQL.Add(' AND books.name_book = :name_book ');
           IBQSearch.ParamByName('name_book').AsString := fmSearchQuery.edBook.Text;
        end;
     if fmSearchQuery.edAuthor.Text <> '' then
        begin
           IBQSearch.SQL.Add(' AND authors.name_avt = :name_avt ');
           IBQSearch.ParamByName('name_avt').AsString := fmSearchQuery.edAuthor.Text;
        end;
     if fmSearchQuery.edPublisher.Text <> '' then
        begin
           IBQSearch.SQL.Add(' AND publishers.name_izd = :name_izd ');
           IBQSearch.ParamByName('name_izd').AsString := fmSearchQuery.edPublisher.Text;
        end;
     if fmSearchQuery.edFirm.Text <> '' then
        begin
           IBQSearch.SQL.Add(' AND firms.name_firm = :name_firm ');
           IBQSearch.ParamByName('name_firm').AsString := fmSearchQuery.edFirm.Text;
        end;
     if (fmSearchQuery.edYearBegin.Text <> '') AND (fmSearchQuery.edYearEnd.Text <> '') then
        if StrToInt(fmSearchQuery.edYearBegin.Text)<=StrToInt(fmSearchQuery.edYearEnd.Text) then
        begin
           IBQSearch.SQL.Add(' AND (books.god_izd BETWEEN :yearbegin AND :yearend) ');
           IBQSearch.ParamByName('yearbegin').AsString := fmSearchQuery.edYearBegin.Text;
           IBQSearch.ParamByName('yearend').AsString := fmSearchQuery.edYearEnd.Text;
        end
        else
        begin
           fmSearchQuery.edYearBegin.Clear;
           fmSearchQuery.edYearEnd.Clear;
           terminate := true;
           incorr_year := true;
        end;
     if (fmSearchQuery.edPriceBegin.Text <> '') AND (fmSearchQuery.edPriceEnd.Text <> '') then
        if StrToInt(fmSearchQuery.edPriceBegin.Text)<=StrToInt(fmSearchQuery.edPriceEnd.Text) then
        begin
           IBQSearch.SQL.Add(' AND (books.price_book BETWEEN :pricebegin AND :priceend) ');
           IBQSearch.ParamByName('pricebegin').AsString := fmSearchQuery.edPriceBegin.Text;
           IBQSearch.ParamByName('priceend').AsString := fmSearchQuery.edPriceEnd.Text;
        end
        else
        begin
           fmSearchQuery.edPriceBegin.Clear;
           fmSearchQuery.edPriceEnd.Clear;
           terminate := true;
           incorr_price := true;
        end;
        if (fmSearchQuery.edBook.Text <> '') OR (fmSearchQuery.edAuthor.Text <> '') OR (fmSearchQuery.edPublisher.Text <> '') OR (fmSearchQuery.edFirm.Text <> '') OR ((fmSearchQuery.edYearBegin.Text <> '') AND (fmSearchQuery.edYearEnd.Text <> '')) OR ((fmSearchQuery.edPriceBegin.Text <> '') AND (fmSearchQuery.edPriceEnd.Text <> '')) then
        if terminate = false then
        begin
          IBQSearch.Prepare;
          IBQSearch.Open;
          if IBQSearch.RecordCount = 0 then ShowMessage('По Вашему запросу ничего не найдено');
        end
        else
          begin
             if (incorr_year = true) then ShowMessage('Диапазон значений годов издания задан некорректно');
             if (incorr_price = true) then ShowMessage('Диапазон значений цен задан некорректно');
          end
        else
        if (incorr_year = false) AND (incorr_price = false) then
            ShowMessage('Вы не задали ни одного параметра')
        else
          begin
             if (incorr_year = true) then ShowMessage('Диапазон значений годов издания задан некорректно');
             if (incorr_price = true) then ShowMessage('Диапазон значений цен задан некорректно');
          end;
end;


Это сообщение отредактировал(а) Gamber - 21.10.2008, 17:21
PM MAIL   Вверх
Deniz
Дата 22.10.2008, 05:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 8
Всего: 44



Gamber, не знаю как сейчас работают IBX (сам общаюсь через FIBPlus), но раньше конструкция вида:
Код

     if fmSearchQuery.edBook.Text <> '' then
        begin
           IBQSearch.SQL.Add(' AND books.name_book = :name_book ');
           IBQSearch.ParamByName('name_book').AsString := fmSearchQuery.edBook.Text;
        end;
не работала.
Между добавлением к SQL параметра и указанием значения нужно было вызывать Prepare, иначе параметры не находились. Как сейчас не знаю.
Далее, дополнить для всех строковых полей
Код
IBQSearch.ParamByName('name_book').AsString := QuotedStr(fmSearchQuery.edBook.Text);

Далее, год издания и цену лучше передавать не AsString а AsInteger/AsFloat.
Далее, для дополнительной функциональности предлагаю разделить период даты издания:
Код
IBQSearch.SQL.Add(' AND (books.god_izd >= :yearbegin) ');
...
IBQSearch.SQL.Add(' AND (books.god_izd <= :yearend) ');
будет возможность искать книги после какого-то года или до какого-то.
Аналогично для цены.
И последнее, лучше сначала проверить правильность введенного в Edit'ы и выдать сообщение об ошибке, а потом формировать SQL-запрос.
Самый простой способ:
Код

var ErrMsg : string;
      IsError : boolean;
...
ErrMsg:='Ошибки!';
IsError:=False;
if <проверка периода> then begin
  IsError:=True;
  ErrMsg:=ErrorMsg + #13 + ' - неправильно введен период';
end;
if <проверка диапазона цен> then begin
  IsError:=True;
  ErrMsg:=ErrorMsg + #13 + ' - неправильно введен диапазон цен';
end;
If IsError then 
  raise Exception.Create(ErrMsg);
как-то так.

Это сообщение отредактировал(а) Deniz - 22.10.2008, 05:51


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Gamber
Дата 22.10.2008, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 24.3.2008

Репутация: нет
Всего: нет



Да вроде бы не было замечено проблем с Prepare, хотя все-таки решил прислушаться, добавил smile 

Вот, что вышло:

Код

procedure TdmBase.aExecuteSearchQueryExecute(Sender: TObject);
var
    incorr_year, incorr_price, empty: boolean;
begin

  // INI //

  empty := false;
  incorr_year := false;
  incorr_price := false;
  aPreviewSearchQuery.Enabled := false;
  IBQSearch.Active := false;
  IBQSearch.Close;
  IBQSearch.SQL.Clear;

  // CHECK //

  if (fmSearchQuery.edBook.Text = '') AND (fmSearchQuery.edAuthor.Text = '') AND (fmSearchQuery.edPublisher.Text = '') AND (fmSearchQuery.edFirm.Text = '') AND (fmSearchQuery.edYearBegin.Text = '') AND (fmSearchQuery.edYearEnd.Text = '') AND (fmSearchQuery.edPriceBegin.Text = '') AND (fmSearchQuery.edPriceEnd.Text = '') then empty := true;

  if (fmSearchQuery.edYearBegin.Text <> '') AND (fmSearchQuery.edYearEnd.Text <> '') then
     if StrToInt(fmSearchQuery.edYearBegin.Text) > StrToInt(fmSearchQuery.edYearEnd.Text) then
        begin
           fmSearchQuery.edYearBegin.Clear;
           fmSearchQuery.edYearEnd.Clear;
           incorr_year := true;
        end;

  if (fmSearchQuery.edPriceBegin.Text <> '') AND (fmSearchQuery.edPriceEnd.Text <> '') then
     if StrToFloat(fmSearchQuery.edPriceBegin.Text) >= StrToFloat(fmSearchQuery.edPriceEnd.Text) then
        begin
           fmSearchQuery.edPriceBegin.Clear;
           fmSearchQuery.edPriceEnd.Clear;
           incorr_price := true;
        end;

  // CREATE QUERY //

  IBQSearch.SQL.text := 'SELECT name_book, name_avt, name_izd, name_firm, god_izd, price_book FROM books, authors, publishes, firms  WHERE ' + ' authors.kod_avt = books.kod_avt AND '+ ' publishes.kod_izd = books.kod_izd AND ' + ' firms.kod_firm = books.kod_firm ';

  if fmSearchQuery.edBook.Text <> '' then
     begin
        IBQSearch.SQL.Add(' AND books.name_book = :name_book ');
        IBQSearch.Prepare;
        IBQSearch.ParamByName('name_book').AsString := fmSearchQuery.edBook.Text;
     end;

  if fmSearchQuery.edAuthor.Text <> '' then
     begin
        IBQSearch.SQL.Add(' AND authors.name_avt = :name_avt ');
        IBQSearch.Prepare;
        IBQSearch.ParamByName('name_avt').AsString := fmSearchQuery.edAuthor.Text;
     end;

  if fmSearchQuery.edPublisher.Text <> '' then
     begin
        IBQSearch.SQL.Add(' AND publishers.name_izd = :name_izd ');
        IBQSearch.Prepare;
        IBQSearch.ParamByName('name_izd').AsString := fmSearchQuery.edPublisher.Text;
     end;

  if fmSearchQuery.edFirm.Text <> '' then
     begin
        IBQSearch.SQL.Add(' AND firms.name_firm = :name_firm ');
        IBQSearch.Prepare;
        IBQSearch.ParamByName('name_firm').AsString := fmSearchQuery.edFirm.Text;
     end;

  if (fmSearchQuery.edYearBegin.Text <> '') then
     begin
        IBQSearch.SQL.Add(' AND (books.god_izd >= :yearbegin) ');
        IBQSearch.Prepare;
        IBQSearch.ParamByName('yearbegin').AsInteger := StrToInt(fmSearchQuery.edYearBegin.Text);
     end;

  if (fmSearchQuery.edYearEnd.Text <> '') then
     begin
        IBQSearch.SQL.Add(' AND (books.god_izd <= :yearend) ');
        IBQSearch.Prepare;
        IBQSearch.ParamByName('yearend').AsInteger := StrToInt(fmSearchQuery.edYearEnd.Text);
     end;

  if (fmSearchQuery.edPriceBegin.Text <> '') then
      begin
         IBQSearch.SQL.Add(' AND (books.price_book >= :pricebegin) ');
         IBQSearch.Prepare;
         IBQSearch.ParamByName('pricebegin').AsFloat := StrToFloat(fmSearchQuery.edPriceBegin.Text);
      end;

  if (fmSearchQuery.edPriceEnd.Text <> '') then
      begin
         IBQSearch.SQL.Add(' AND (books.price_book <= :priceend) ');
         IBQSearch.Prepare;
         IBQSearch.ParamByName('priceend').AsFloat := StrToFloat(fmSearchQuery.edPriceEnd.Text);
      end;

  if (fmSearchQuery.comboSort.ItemIndex = 0) then
      begin
         IBQSearch.SQL.Add(' ORDER BY name_book ');
         IBQSearch.Prepare;
      end;

  if (fmSearchQuery.comboSort.ItemIndex = 1) then
      begin
         IBQSearch.SQL.Add(' ORDER BY name_avt ');
         IBQSearch.Prepare;
      end;

  if (fmSearchQuery.comboSort.ItemIndex = 2) then
      begin
         IBQSearch.SQL.Add(' ORDER BY name_izd ');
         IBQSearch.Prepare;
      end;

  if (fmSearchQuery.comboSort.ItemIndex = 3) then
      begin
         IBQSearch.SQL.Add(' ORDER BY name_firm ');
         IBQSearch.Prepare;
      end;

  if (fmSearchQuery.comboSort.ItemIndex = 4) then
      begin
         IBQSearch.SQL.Add(' ORDER BY god_izd ');
         IBQSearch.Prepare;
      end;

  if (fmSearchQuery.comboSort.ItemIndex = 5) then
      begin
         IBQSearch.SQL.Add(' ORDER BY price_book ');
         IBQSearch.Prepare;
      end;

  // EXECUTE QUERY //

  if incorr_year = false then
     if incorr_price = false then
        if empty = false then
           begin
              IBQSearch.Prepare;
              IBQSearch.Open;
              if IBQSearch.RecordCount = 0 then
                 ShowMessage('По Вашему запросу ничего не найдено')
              else
                 aPreviewSearchQuery.Enabled :=true;
            end
         else
         ShowMessage('Вы не задали ни одного параметра')
      else
      ShowMessage('Диапазон значений цен задан некорректно')
   else
   ShowMessage('Диапазон значений годов издания задан некорректно')
end;


Правда есть пара нюансов:

1. Если добавить конструкцию типа:
Код

   QuotedStr(fmSearchQuery.edBook.Text)

то результат всегда пустой, как я понял как раз из-за кавычек которые добавляются в начале и конце...

2. Скажите как сделать корректнее, так:

Код

 StrToInt(fmSearchQuery.edYearBegin.Text) > StrToInt(fmSearchQuery.edYearEnd.Text)
 StrToFloat(fmSearchQuery.edPriceBegin.Text) > StrToFloat(fmSearchQuery.edPriceEnd.Text)


или так:

Код

 fmSearchQuery.edYearBegin.Text > fmSearchQuery.edYearEnd.Text
 fmSearchQuery.edPriceBegin.Text > fmSearchQuery.edPriceEnd.Text


Добавлено через 9 минут и 14 секунд
И еще забыл, добавил контроль ввода на поля годов и цен...
Для года издания:
Код

  if not (Key in ['0'..'9',#8]) then Key := #0;


Для цены, вот такой вариант нашел:
Код

var //цифровая маска
  vrPos,vrLength,vrSelStart : byte;
const
  I : byte=1; //I+1 = количество знаков после запятой (в данном случае - 2 знака)
begin
  With Sender as TJvEdit do
  begin
    vrLength:=Length(Text); //определяем длину текста
    vrPos:=Pos(',', Text); //проверяем наличие запятой
    vrSelStart:=SelStart; //определяем положение курсора
    end;

  Case Key of

    '0'..'9' :
      begin
        //проверяем положение курсора и количество знаков после запятой
        If (vrPos>0)and(vrLength-vrPos>I)and(vrSelStart>=vrPos) then Key:=#0; //"погасить" клавишу
      end;

    ',','.' :
      begin
        //если запятая уже есть или запятую пытаются поставить перед числом или никаких цифр в поле ввода еще нет
        If (vrPos>0)or(vrSelStart=0)or(vrLength=0) then Key:=#0 //"погасить" клавишу
        else Key:=#44; //всегда заменять точку на запятую
      end;

    #8 : ; //позволить удаление знаков клавишей 'Back Space'
        else Key := #0; //"погасить" все остальные клавиши
  end;


Это сообщение отредактировал(а) Gamber - 22.10.2008, 17:58
PM MAIL   Вверх
Deniz
Дата 23.10.2008, 05:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 8
Всего: 44



Цитата(Gamber @  22.10.2008,  20:57 Найти цитируемый пост)
2. Скажите как сделать корректнее
однозначно
Код
StrToInt(fmSearchQuery.edYearBegin.Text) <= StrToInt(fmSearchQuery.edYearEnd.Text)
если сравнивать строки, то 123 < 99
Контроль для ввода года и цены, ИМХО, не нужен в таком виде.
Во-первых, ты гасишь кнопки стрелка влево/вправо/home/end, delete, к которыми пользователь возможно привык.
Во-вторых, существуют готовые компоненты для ввода цифр. (У тебя TJvEdit может там что-то есть).
В-третьих, можно проще проверить правильность ввода через try except.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Gamber
Дата 23.10.2008, 05:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 24.3.2008

Репутация: нет
Всего: нет



Цитата(Deniz @ 23.10.2008,  05:21)
Цитата(Gamber @  22.10.2008,  20:57 Найти цитируемый пост)
2. Скажите как сделать корректнее
однозначно
Код
StrToInt(fmSearchQuery.edYearBegin.Text) <= StrToInt(fmSearchQuery.edYearEnd.Text)
если сравнивать строки, то 123 < 99
Контроль для ввода года и цены, ИМХО, не нужен в таком виде.
Во-первых, ты гасишь кнопки стрелка влево/вправо/home/end, delete, к которыми пользователь возможно привык.
Во-вторых, существуют готовые компоненты для ввода цифр. (У тебя TJvEdit может там что-то есть).
В-третьих, можно проще проверить правильность ввода через try except.

Ага, понял...

По контроль ввода да, сначала хотел решить вопрос компонентом, MaskEdit как я понял здесь не пойдет (возникает проблема преобразования в число проблелов)... Попробую покопать JvEdit...

Кстати стрелки и delete работают по-умолчанию, а Backspace прописан (#8), хотя соглашусь, это конечно не самое лучшее решение...

Deniz большое тебе спасибо за помощь, сток косяков удалось откопать smile
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.1408 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.