Поиск:

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


Шустрый
*


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

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



Всем доброго времени суток помогите пожалуйста разобраться...

Есть БД "Библиотека" в оболочке которая реализуется под эту базу я создаю параметризированный SELECT-запрос для поиска книги, в качестве параметров могут использоваться: название книги, имя автора, название издательства, название книготорговой фирмы значение параметров задается пользователем в обычных edit полях...

Необходимо чтобы пользователь мог задавать произвольное число параметров... Допустим введено: "Пушкин", остальные Edit пустые, результат все книги Пушкина, или к примеру введено "Пушкин" "Питер", результат все книги Пушкина изданные издательством Питер...

Код

      IBQSearchByName.Params[0].Value := fmSearchQuery.edBook.Text;
      IBQSearchByName.Params[1].Value := fmSearchQuery.edAuthor.Text;
      IBQSearchByName.Params[2].Value := fmSearchQuery.edPublisher.Text;
      IBQSearchByName.Params[3].Value := fmSearchQuery.edFirm.Text;      
      IBQSearchByName.Close;
      IBQSearchByName.Open;
      if fmSearchQuery.ehSearchQuery.SumList.RecordCount = 0 then
      ShowMessage('По Вашему запросу ничего не найдено');


А вот с SQL запросом возникили проблемы, сначала писал:
Код

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 AND
(name_book = :name_book OR
name_avt = :name_avt OR
name_izd = :name_izd OR
name_firm = :name_firm)
ORDER BY name_book


В этом случае получал из-за "OR" получался не уточняющий поиск, а обобщающий (весь Пушкин, весь Питер), при замене на "AND" работает лучше, но необходимо вводить все параметры иначе поиск не осуществится...

Предложили попробовать сделать так:

Код

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 AND
(name_book = :name_book or :name_book is null) and 
(name_avt = :name_avt or :name_avt  is null) and 
(name_izd = :name_izd or :name_izd is null) and 
(name_firm = :name_firm or :name_firm is null)
ORDER BY name_book


Сделал, но теперь получаю ошибку от сервера:
Код
'Dynamic SQL Error SQL error code =-804 Data type unknown'


На данный момент для реализации поставленной задачи получается использовать только отдельные запросы с одним параметром (поиск по названию книги - один запрос с одним параметром типа:

Код
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 AND
name_book = :name_book
ORDER BY name_book


и т.д

Минусы очевидны: много практически идентичных запросов, нет возможности уточняющего поиска по нескольким параметрам (т.е нельзя искать все книги Пушкина изданные издательством "Питер", к примеру, а можно искать только все книги Пушкина или все книги изданные издательством "Питер")...

Может все-таки есть решение этой проблемы? Подскажите пожалуйста...

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


Эксперт
***


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

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



Код
...
and
(name_book = :name_book or :name_book is null)
and
...
нормальный вариант, и он работает(напиши его в IBExpert и посмотри), ищи причины ошибки.
Минусы: использование индексов зависит от ума оптимизатора.

Есть еще вариант динамически формировать запрос на клиенте:
Код

  if fmSearchQuery.edBook.Text <> '' then
    IBQSearchByName.SQL.Add('  and (name_book = :name_book) ');
  ...
  IBQSearchByName.Prepare;
  if fmSearchQuery.edBook.Text <> '' then
    IBQSearchByName.ParamByName('name_book').AsString := fmSearchQuery.edBook.Text;
  ...
тоже рабочий вариант, но усложняется внесение изменений, зато индексы используются по полной программе.


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


Бывалый
*


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

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



А Like не подходит?


PM MAIL   Вверх
Frees
Дата 21.10.2008, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

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



Цитата(Gamber @  21.10.2008,  10:32 Найти цитируемый пост)
'Dynamic SQL Error SQL error code =-804 Data type unknown'


Код

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 AND
(name_book = cast(:name_book as varchar(100)) or :name_book is null) and 
(name_avt = cast(:name_avt as varchar(100)) or cast(:name_avt as varchar(100))   is null) and 
-- и тд...
ORDER BY name_book


ошибка должна пропасть

Добавлено через 4 минуты и 20 секунд
Цитата(Deniz @  21.10.2008,  10:58 Найти цитируемый пост)
тоже рабочий вариант, но усложняется внесение изменений, зато индексы используются по полной программе.

думеш есть смысл индексировать по этим полям?

Это сообщение отредактировал(а) Frees - 21.10.2008, 10:58


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Gamber
Дата 21.10.2008, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Deniz @ 21.10.2008,  08:58)
[code=sql]...
Есть еще вариант динамически формировать запрос на клиенте:
Код

  if fmSearchQuery.edBook.Text <> '' then
    IBQSearchByName.SQL.Add('  and (name_book = :name_book) ');
  ...
  IBQSearchByName.Prepare;
  if fmSearchQuery.edBook.Text <> '' then
    IBQSearchByName.ParamByName('name_book').AsString := fmSearchQuery.edBook.Text;
  ...
тоже рабочий вариант, но усложняется внесение изменений, зато индексы используются по полной программе.

Решил сделать динамически... Для начала для пары полей (книга и автор):
Код

// Код на открытие формы запрса (грид, поля ввода параметров, кнопки)

begin 
  gbBooks.Refresh;
  fmSearchQuery.ShowModal;
  fmSearchQuery.edit1.Clear;
  fmSearchQuery.edit2.Clear;
end;

// Код на кнопку выполнить запрос

 begin
      fmSearchQuery.ehSearchQuery.DataSource := dmBase.dsSearchByName;
      IBQSearchByName.Close;
          if fmSearchQuery.Edit1.Text <> '' then
               begin
                   IBQSearchByName.SQL.Add(' AND name_avt = :name_avt ');
                   IBQSearchByName.ParamByName('name_avt').AsString := fmSearchQuery.Edit1.Text;
               end;
          if fmSearchQuery.Edit2.Text <> '' then
               begin
                   IBQSearchByName.SQL.Add(' AND name_book = :name_book ');
                   IBQSearchByName.ParamByName('name_book').AsString := fmSearchQuery.Edit2.Text;
               end;
          IBQSearchByName.Prepare;
          IBQSearchByName.Open;
          fmSearchQuery.Edit2.Text := '';
          fmSearchQuery.Edit1.Text := '';
          if fmSearchQuery.ehSearchQuery.SumList.RecordCount = 0 then
               ShowMessage('По Вашему запросу ничего не найдено');


SQL Запрос вот такой:

Код

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


Столкнулся с двумя проблемами:

1. При открытии окна запроса, сразу исполняется SQL запрос, полная выборка из базы... Можно ли это предотвратить и сделать так, чтобы выводились данные в грид только после нажатия на кнопку "Выполнить запрос"?

2. Допустим я ввел: "Сказки", пустой ответ (ничего не найдено), хотя две таких книги есть Пушкина и Гоголя, ввел в поле автора Гоголь увидел книгу, ввел Пушкина тоже OK...
И например так ввел Пушкин увидел все его книги, ввел Сказки увидел его книгу, поменял на гоголя тоже нормально, а начинаю вновь вводить просто Пушкин, вижу только Сказки...

Вообщем что-то я запутался... Подскажите пожалуйста где я мог ошибиться?

Frees, та же самая ошибка...

Это сообщение отредактировал(а) Gamber - 21.10.2008, 11:14
PM MAIL   Вверх
Frees
Дата 21.10.2008, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

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



Цитата(Gamber @  21.10.2008,  13:05 Найти цитируемый пост)
та же самая ошибка...

cast может не у всех параметров стоит
зы динамичесски лучше

Цитата(Gamber @  21.10.2008,  13:05 Найти цитируемый пост)
1. При открытии окна запроса, сразу исполняется SQL запрос, полная выборка из базы... Можно ли это предотвратить и сделать так, чтобы выводились данные в грид только после нажатия на кнопку "Выполнить запрос"?



IBQSearchByName.active false в свойствах поставь

когда на кнопку нажмеш он выполниться

по поводу 2 вопрса попробуй так -
Код

// Код на кнопку выполнить запрос

 begin
      fmSearchQuery.ehSearchQuery.DataSource := dmBase.dsSearchByName;
      IBQSearchByName.Close;
     IBQSearchByName.SQL.text := 'SELECT name_book, name_avt, name_izd, name_firm, god_izd, price_book FROM books, authors, publishes, firms  '
          if fmSearchQuery.Edit1.Text <> '' then
               begin
                   IBQSearchByName.SQL.Add(' where name_avt = '#39+ fmSearchQuery.Edit1.Text+#39);
               end;
          if fmSearchQuery.Edit2.Text <> '' then
               begin
                  if fmSearchQuery.Edit1.Text <> '' 
                    then BQSearchByName.SQL.Add(' AND ')
                    else BQSearchByName.SQL.Add(' where ')
                   IBQSearchByName.SQL.Add(' name_book = '#39+fmSearchQuery.Edit2.Text+#39);
               end;
          IBQSearchByName.Prepare;
          IBQSearchByName.Open;
         
         // fmSearchQuery.Edit2.Text := ''; также не удобна если условия поиска будут очищаться
         // fmSearchQuery.Edit1.Text := '';
          if IBQSearchByName.RecordCount = 0 then
               ShowMessage('По Вашему запросу ничего не найдено');


Это сообщение отредактировал(а) Frees - 21.10.2008, 11:33


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Gamber
Дата 21.10.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Код

 IBQSearchByName.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

PM MAIL   Вверх
Frees
Дата 21.10.2008, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

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



Цитата(Gamber @  21.10.2008,  13:42 Найти цитируемый пост)
А разве не нужно еще дописать связь?

да нужно не заметил просто

Добавлено @ 11:47
вот так значит
Код

//......
     IBQSearchByName.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.Edit1.Text <> '' then
               begin
                   IBQSearchByName.SQL.Add(' AND name_avt = '#39+ fmSearchQuery.Edit1.Text+#39);
               end;
          if fmSearchQuery.Edit2.Text <> '' then
               begin
                   IBQSearchByName.SQL.Add(' AND name_book = '#39+fmSearchQuery.Edit2.Text+#39);
               end;
//.....


Это сообщение отредактировал(а) Frees - 21.10.2008, 11:48


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Gamber
Дата 21.10.2008, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Код

begin
   if fmSearchQuery.SearchMode.ItemIndex = 1 then
    begin
     fmSearchQuery.ehSearchQuery.DataSource := dmBase.dsSearchByName;
     IBQSearchByName.Close;
     IBQSearchByName.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.Edit1.Text <> '' then
        begin
          IBQSearchByName.SQL.Add(' AND name_avt = '#39+ fmSearchQuery.Edit1.Text+#39);
        end;
     if fmSearchQuery.edValue.Text <> '' then
        begin
          IBQSearchByName.SQL.Add(' AND name_book = '#39+fmSearchQuery.edValue.Text+#39);
        end;
     if fmSearchQuery.edValue.Text <> '' then
        begin
          if fmSearchQuery.Edit1.Text <> '' then
            IBQSearchByName.SQL.Add(' AND ')
          else
            IBQSearchByName.SQL.Add(' where ');
          IBQSearchByName.SQL.Add(' name_book = '#39+fmSearchQuery.edValue.Text+#39);
        end;
     IBQSearchByName.Prepare;
     IBQSearchByName.Open;
     if IBQSearchByName.RecordCount = 0 then
        ShowMessage('По Вашему запросу ничего не найдено');
  end;


Не хочет работать... Запрос вообще не выполняется... Ругается "Empty SQL Statment"
PM MAIL   Вверх
Frees
Дата 21.10.2008, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

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



Код

begin
   if fmSearchQuery.SearchMode.ItemIndex = 1 then
    begin
     fmSearchQuery.ehSearchQuery.DataSource := dmBase.dsSearchByName;
     IBQSearchByName.Close;
     IBQSearchByName.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.Edit1.Text <> '' then
        begin
          IBQSearchByName.SQL.Add(' AND authors.name_avt = '#39+ fmSearchQuery.Edit1.Text+#39);
        end;
     if fmSearchQuery.edValue.Text <> '' then
        begin
          IBQSearchByName.SQL.Add(' AND books.name_book = '#39+fmSearchQuery.edValue.Text+#39);
        end;
 {    if fmSearchQuery.edValue.Text <> '' then //это уже не надо
        begin
          if fmSearchQuery.Edit1.Text <> '' then
            IBQSearchByName.SQL.Add(' AND ')
          else
            IBQSearchByName.SQL.Add(' where ');
          IBQSearchByName.SQL.Add(' name_book = '#39+fmSearchQuery.edValue.Text+#39);
        end; }
     IBQSearchByName.Prepare;
     IBQSearchByName.Open;
     if IBQSearchByName.RecordCount = 0 then
        ShowMessage('По Вашему запросу ничего не найдено');
  end;

 IBQSearchByName - это что за компонент?

Это сообщение отредактировал(а) Frees - 21.10.2008, 12:14


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Gamber
Дата 21.10.2008, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Frees @ 21.10.2008,  12:12)
IBQSearchByName - это что за компонент?

IBQuery
PM MAIL   Вверх
vovk
Дата 21.10.2008, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Код

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 AND
(name_book Like "'+fmSearchQuery.edBook.Text+'%") and 
(name_avt Like "'+fmSearchQuery.edAuthor.Text+'%") and 
(name_izd Like "'+ fmSearchQuery.edPublisher.Text+'%") and 
(name_firm Like "'+fmSearchQuery.edFirm.Text+'%")
ORDER BY name_book



А в таком виде не пойдёт?

Единственно что будет отсеивать записи с пустыми значениями из этих полей

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


Шустрый
*


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

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



Цитата(vovk @ 21.10.2008,  12:14)
Код

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 AND
(name_book Like "'+fmSearchQuery.edBook.Text+'%") and 
(name_avt Like "'+fmSearchQuery.edAuthor.Text+'%") and 
(name_izd Like "'+ fmSearchQuery.edPublisher.Text+'%") and 
(name_firm Like "'+fmSearchQuery.edFirm.Text+'%")
ORDER BY name_book



А в таком виде не пойдёт?

Единственно что будет отсеивать записи с пустыми значениями из этих полей

Нет врядли...
PM MAIL   Вверх
Gamber
Дата 21.10.2008, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ВСЕ! Вроде бы заработало smile

Frees, Большое спасибо!

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


Эксперт
***


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

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



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


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
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   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0838 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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