Всем привет, сегодня мы рассмотрим урок, связанный с Базами данных, а в частности мы рассмотрим, как сделать подсказку пользователю, который вводит данные, например, для поиска. Данную функцию можно наблюдать во многих программах, а также на многих сайтах, например, Вконтакте, когда происходит поиск человека, появляется выпадающий список, в котором можно найти похожие совпадения, что облегчает ввод данных пользователю, данную функцию мы опробуем и на Delphi на примере Базы данных MS Access, только немного в простом варианте. Но это подходит и к другим БД, которые можно использовать в Delphi. Мы уже много рассматривали примеров, для поиска данных, в этом случае мы будем использовать SQL-конструкцию LIKE, которую раньше мы также рассматривали и использовали. Пример данной конструкции описан ниже:

SELECT имя_столбца FROM имя_таблицы WHERE имя поля LIKE имя_входного_параметра

Как видно выше, конструкция LIKE проста для поиска данных по шаблону, для нее необходимо указать один входной параметр.

А теперь приступим к нашему примеру и задачи. Для начала давайте создадим некоторую Базу данных в MS Access, не будем слишком усложнять пример, это Вы сможете сделать и сами, а просто сделаем одну табличку, назовем ее Goroda, в ней я создал следующие поля:

  • Id – счетчик
  • Gorod – Текстовый

Теперь нам необходимо немного заполнить нашу табличку, совсем не много, я добавил туда всего-навсего 5 записей:


Саму структуру таблицы, вы можете увидеть на рисунке:


Идем дальше, для примера, создадим проект в Delphi, на форме разместим следующие компоненты:

  • TADOQuery
  • TADOConnection
  • TEdit
  • Tlabel

В свойстве Caption компонента TLabel напишем – «Город». Далее выделяем компонент TAdoConnection, в его свойстве ConnectionString указываем Поставщика данных – в нашем случае это Microsoft Jet 4.0 OLE DB Provider. Переходим к следующему пункту подключения (вкладке), в которой указываем путь к нашей Базе данных (можно указать полный путь к Базе данных, но если она находится в текущей папке с проектом, то просто указываем полное имя нашей Базы данных с расширением, в нашем случае *.mdb). Нажимаем OK и переходим к свойству Mode, в котором выбираем из выпадающего списка cmShareDenyNone, хотя можно просто выбрать чтение cmShareDenyRead. Ну и  свойство LoginPromt ставим в False (запрещаем выводить окно, для запроса ввода имени и пароля, который позволяет получить доступ к нашей Базе данных), если конечно в Вашей Базе данных не установлен пароль, в противном случае Вам придется вводить логин и пароль, можно это забить в нашем подключении, чтобы постоянно не вводить одни и теже данные. Я пароль на Базу данных не ставил, поэтому устанавливаем в False. Ну и наконец нам необходимо активировать подключение к нашей Базе данных, для этого свойство Connected устанавливаем в False.

Теперь переходим к настройке нашего компонента TADOQuery. Выделяем наш компонент TADOQuery и в свойстве Connection указываем имя компонента TADOConnection, в моем случае это AdoConnection1. Далее нам понадобиться еще одно свойство компонента TADOQuery – это Parameters. Открываем его и добавляем новый параметр (его название), я его назвал – gorods, указываем ему тип данных (DataType) – ftString и все закрываем наше окно. Сразу активировать наш запрос не надо, так как в нем мы не прописали никакой SQL-конструкции, да и Вам собственно это не удастся. Общий вид моего окна проекта получился следующим:

Теперь переходим к написанию кода программы.

Выделяем наш компонент TEdit и переходим в список его событий, находим там событие OnKeyUp и нажимаем двойным щелчком, для открытия окна кода программы для этого события. Почему именно данное событие, потому что оно нам само больше подходит, оно возникает, генерируется после того, как пользователь ввел очередной символ город и уже отпускает кнопку, также в данном событии имеется аргумент Key, который хранит числовой код нажатой клавиши.

Теперь переходим к написание кода, открываем еще раз наше событие и пишем туда следующий код:

procedure TForm1.Edit1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  pos:word;
  s:string;
begin
   if Key>47 then
    begin
     Edit1.ClearSelection;
     Pos:=Length(Edit1.Text);
     ADOQuery1.SQL.Add('SELECT Gorod FROM Goroda WHERE Gorod LIKE :gorods');
     ADOQuery1.Parameters.ParamValues['gorods']:=Trim(Edit1.Text)+'%';
     ADOQuery1.Active:=True;
     with ADOQuery1 do
      begin
       if Active then
        Close;
       Open;
       if FieldByName('Gorod').IsNull=False then
        begin
        Edit1.Text:=fieldbyname('Gorod').AsString;
        Edit1.SelStart:=Pos;
        Edit1.SelLength:=length(Edit1.Text)-1;
        ADOQuery1.SQL.Clear;
        end
       else MessageBeep(0);
      end;
    end;
end;

Теперь давайте детально разберем наш код. Переменная pos, нам необходима для запоминания текущей позиции ввода. Дальше в условии мы отсеиваем все коды клавиш которые меньше 47.

С помощью ClearSelection мы снимаем выделение в компоненте TEdit. Дальше мы пишем наш SQL-запрос, в котором и присутствует конструкция LIKE, а в ней мы указываем в условии наш параметр gorods. Уже нижней строчкой мы задаем нашему параметру значения из TEdit, для начала удалив все пробелы, которые могут быть впереди, а также вконец нашей записи добавляем символ %, который дает понять запросу, что после введенного пользователем слова могут идти совершенно любые символы.

В конце все просто, мы присваиваем в TEdit, то что нашли в Базе данных (если нашли конечно), и выделяем в слове те символы, которые возможно пользователь и ищет, если ничего не нашли, то издаем просто звуковой сигнал. Вот, что у меня примерно получилось:

Что касается этой темы, то ее можно развить и дальше. Так как в данном примере показывается только результат первой найденной записи в таблице, а схожих может быть и не сколько, поэтому тут можно сделать в виде выпадающего списка, как я упоминал раньше реализовано в известной социальной сети Вконтакте. Поэтому данный пример, мы рассмотрим уже в следующих статьях по Базам данных.

А что касается данного примера, то основные его достоинства состоят в том, что он не только находит название города, который соответствует шаблону LIKE, но и также помогает пользователю закончить ввод, подставляя наиболее подходящее название города.

Поэтому используется в своих разработках именно данную конструкцию поиска, чтобы облегчить пользователю работать в Вашей программе. Также я выкладываю исходники статьи, которые можно скачать тут. Исходник проверялся в IDE – Delphi 7.

До встречи, жду Вас в следующих статьях.

 




К записи “Конструкция LIKE в запросе. Делаем удобный поиск” оставлено комментариев: 20.

  1. Вот, кстати, вопрос.
    Когда Вы будете делать поиск в ComboBox (часть 2), то есть одна из альтернатив (видных на первый взгляд):
    — добавить ORDER BY gorod, чтобы в откидывающемся списке показывать города по алфавиту;
    — вести статистику (динамическую, статическую) по пользователям в городах, чтобы затем упорядочить «подсказки» городов по их популярности;

    В любом случае — удачи!

  2. Конструкция
    ADOQuery1.Active:=True;
    with ADOQuery1 do
    begin
    if Active then
    Close;
    Open;
    ...

    Для чего это сделано? Ведь внутри Open происходит как раз Active:=True. Получается что вначале вы делаете Open, потом проверяете активен ли квери, если да, то закрываете и потом тут же снова открываете. Но при таком коде у вас всегда квери перед проверкой будет открыт. Объясните, зачем это сделано?
    З.Ы. Да кстати, возможно стоит сделать паузу между вводом последнего символа и поиском данных. Т.к. если данных в БД будет много, то после каждого ввода символа будут тормоза, что может не понравится пользователю. Пауза в полсекунды вполне приемлемо (если пользователь вводит текст быстро)

  3. Много раз делал автозавершение вводимого слова — перепробовал массу вариантов. Так вот самый оптимальный — инициализировать поиск по таймеру. Т.е. пользователь надавил кнопку — таймер начал отсчет (например 500 мс), если нажал еще раз — то начинается отсчет заново. По срабатыванию таймера — выполнение запроса.
    Ну и вообще, если справочник не большой — то проще зафетчить его весь в комбобокс, а уж он сам все будет завершать без изобретения велосипеда. Вот на больших таблицах — приходится извращаться

  4. Сергей:

    доброго времени суток,помогите мне пожалуйста,наткнулся на эту страницу в сети,спасибо Вам за такое пояснение во всем,но у меня есть проблема:
    У меня есть Б/Д,2 таблицы они между собой не связаны.
    Таблицы были связаны с помощью компонентов ADOQUERY,ADOCONNECTION,DBGRID,DATASOURCE.
    и таких 2 таблицы,скажите мне пожалуйста как связать их между собой ???? возможно ли это без ADOTABLE???
    и мне нужно чтоб из таблицы №2 по выбранной строке он вырезал запись и вставлял в таблицу№1. Возможна ли реализация такого кода,с такой конструкцией??????????

    • Andrey:

      Можно связывать путем введения ключевых полей и делать запросы по выборке в соответсвии с ключевым полем, а можно почитать статью — http://devdelphi.ru/?p=1271 и связать поле

  5. Elena:

    Андрей, у Вас настолько полезный сайт. Спасибо Вам за него. У меня вопрос. При программировании на Delphi, я использую таблицы БД Paradox и результат меня не очень радует. Иногда данные в таблицу не записываются вовсе. А где создавать таблицы БД посоветовали бы Вы? Спасибо.

    • Andrey:

      здравствуйте, я бы использовал какие-нибудь бесплатные СУБД, MySQL — хорошая, MS Access тоже хороша, но надо покупать, еще мне нравиться FireBird, MS SQL отличная, вообще ряд есть СУБД хороших как платных так и бесплатных, смотря для каких Вы целей будете использовать

  6. Анна:

    Андрей,здравствуйте. У меня почему-то синтаксическая ошибка в этой строке: ADOQuery1.SQL.Add(‘SELECT FIO * FROM tbFamilii WHERE FIO LIKE :familia’);
    От чего это может быть?

  7. Василий:

    ОЧЕНЬ интересует подбор с выпадающим списком
    PS пишу диплом и такая функция бы мне очент там пригодилась

  8. Deika:

    у меня выдает ошибку при поиске все норм но еси нет этой фамилии в базе выдается эта ошибка и дальше поиск не идет.

  9. Deika:

    у меня выдает ошибку
    Неправильно определен объект Parameter. Передоставлены несовместимые или неполные сведения
    при поиске все норм но еси нет этой фамилии в базе выдается эта ошибка и дальше поиск не идет.

  10. Maxim:

    Можно ли поиск организовать сразу из нескольких полей?
    Пробывал в запросе написать ‘SELECT * FROM Users WHERE Name LIKE :nm OR LastName LIKE :nm’ ищет только по полю Name :(

  11. Марина:

    При вводе города которого нет, вылетает ошибка Неправильно определен объект Parameter. Передоставлены несовместимые или неполные сведения.

  12. Berto:

    Добрый день.
    Андрей, подскажите пожалуйста, как в базе данных (DELPHI 7 MS Access 2003) конструкцию LIKE «уговорить» быть чувствительной к регистру?

Оставить комментарий

Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*