Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Поиск по БД через SQL


Автор: Palladin 20.4.2006, 23:49
Вообщем делаю курсач, всё сделано, но одна функция не пашет:

короче при нажатии на кнопку "Поиск" появляется новая форма в которой есть dbgrid и 4 edit-a
есть возможность искать по одному из полей(это работаетsmile) а вот, я ещё хочу сделать так чтобы пользователь повводил всё что помнит, может он введёт записи только в первые два edit-a, а может и во все, и чтоб по тому что он ввёл шёл поиск

Вот код поиска по одному из полей:

Код

procedure TForm5.Button2Click(Sender: TObject);
begin
form1.ADOQuery1.Active:=false;
form1.ADOQuery1.SQL.clear;
form1.ADOQuery1.SQL.Add('SELECT *');
form1.ADOQuery1.SQL.Add('FROM BOOK');
if length(edit1.Text)>0 then
form1.ADOQuery1.SQL.add('Where [Шифр книги] LIKE'''+edit1.Text+'''');
form1.ADOQuery1.Active:=true;
edit1.clear;
end;



Это работает, а вот при нажатии на кнопку поиск по всем полям что-то не выходит, ошибки пишетsmile((((
вот то что я написал в коде поиск по всем полям



Код

procedure TForm5.Button6Click(Sender: TObject);
begin
form1.ADOQuery1.Active:=false;
form1.ADOQuery1.SQL.clear;
form1.ADOQuery1.SQL.Add('SELECT *');
form1.ADOQuery1.SQL.Add('FROM BOOK');
if length(edit4.Text)>0 then
form1.ADOQuery1.SQL.add('Where Издательство LIKE'''+edit1.Text+'''');
form1.ADOQuery1.Active:=true;

form1.ADOQuery1.Active:=false;
form1.ADOQuery1.SQL.clear;
form1.ADOQuery1.SQL.Add('SELECT *');
form1.ADOQuery1.SQL.Add('FROM BOOK');
if length(edit3.Text)>0 then
form1.ADOQuery1.SQL.add('Where Название LIKE'''+edit1.Text+'''');
form1.ADOQuery1.Active:=true;

form1.ADOQuery1.Active:=false;
form1.ADOQuery1.SQL.clear;
form1.ADOQuery1.SQL.Add('SELECT *');
form1.ADOQuery1.SQL.Add('FROM BOOK');
if length(edit2.Text)>0 then
form1.ADOQuery1.SQL.add('Where Автор LIKE'''+edit1.Text+'''');
form1.ADOQuery1.Active:=true;

form1.ADOQuery1.Active:=false;
form1.ADOQuery1.SQL.clear;
form1.ADOQuery1.SQL.Add('SELECT *');
form1.ADOQuery1.SQL.Add('FROM BOOK');
if length(edit1.Text)>0 then
form1.ADOQuery1.SQL.add('Where [Шифр книги] LIKE'''+edit1.Text+'''');
form1.ADOQuery1.Active:=true;
end;




Помогите здесь подправить smile  

Автор: Fast 21.4.2006, 05:53
Цитата(RooR @  20.4.2006,  23:49 Найти цитируемый пост)
Помогите здесь подправить smile   


Извини придётся всё переделывать  smile 

Вот как всё должно быть  smile
Код

procedure TForm5.Button6Click(Sender: TObject);
var
mFilter, nFilter, xFilter : String;
begin
With Form1 do
begin
ADOQuery1.Active := False;
ADOQuery1.SQL.Clear;
mFilter := 'Select * From BOOK Where ';
nFilter := '';
if Edit1.Text <> '' then
nFilter := nFilter + ' AND Издательство LIKE''' + Edit1.Text + '''';
if Edit2.Text <> '' then
nFilter := nFilter + ' AND Название LIKE''' + Edit2.Text + '''';
if Edit3.Text <> '' then
nFilter := nFilter + ' AND Автор LIKE''' + Edit3.Text + '''';
if Edit4.Text <> '' then
nFilter := nFilter + ' AND [Шифр книги] LIKE''' + Edit4.Text + '''';
Delete(nFilter,1,5);
xFilter := mFilter + nFilter;
ShowMessage(xFilter); // Это используется чтобы посмотреть как выглядет твой запрос ПОТОМ УДАЛИ!!!!
ADOQuery1.SQL.Text := xFilter;
ADOQuery1.ExecSQL;
end
end;


 

Автор: Palladin 21.4.2006, 17:34
К сожалению здесь что-то не так, поиск не отображается в dbedite, при нажатии на кнопку поиск по всем полям, весь dbgrid очищается, какбудто конект проподает к adoconnection smile  

Автор: sexton 21.4.2006, 18:39
Имхо Open, а не ExecSQl... ExecSQL вроде не возвращает курсор для отображения

Автор: Palladin 21.4.2006, 23:14
Нет Open тоже не катит, ошибку выдаёт, ошибка синтаксиса и т.п. smile  

Автор: x77 22.4.2006, 01:15
ну блин....   ну дурные проблемы ведь. 

гляди. открой пустой проект. кинь на форму обычный Query (в DatabaseName поставь "DBDEMOS"), DataSource, привязанный к этому квери, DBGrid, привязанный к датасорсу, кинь на форму четыре TEdit и одну педаль сиречь TButton. в Query1.SQL напиши 'select * from biolife'. вот код всего проекта:

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, DBTables, DB, StdCtrls, Grids, DBGrids;

const
  // количество полей, по которым мы будем фильтровать
  FilterNum = 4; 

  // имена этих полей
  FieldNames: array [1..FilterNum] of string =
    ('SpeciesNo', 'Category', 'Common_Name', 'Species Name');

  // основной запрос, к которому будет добавляться динамический сформированный фильтр
  SelectClause: string =
    'select * from biolife';

type
  TForm1 = class(TForm)
    Query1: TQuery;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  // собственно, будущий фильтр
  WhereClause: string;
  i: integer;
  Edit: TEdit;
begin
  WhereClause := '';
  // перебираем фильтрумые поля, см (1) в конце.
  for i := 1 to FilterNum do begin
    // находим Edit для i-го поля, подразумевая что все едиты названы стандартно
    Edit := (FindComponent ('Edit' + IntToStr (i)) as TEdit);
    // обязательная проверка на nil - т.е. мы убеждаемся, что мы свой едит нашли
    if (Edit <> nil) and (Edit.Text <> '') then begin
      // если фильтр не пустой, то надо добавить OR к предыдущему условию
      if WhereClause <> '' then
        WhereClause := WhereClause + ' OR ';
      // добавляем к фильтру слеюующее условие
      WhereClause := WhereClause + '(' + FieldNames [i] + ' like ''%' + Edit.Text + '%'')';
    end;
  end;
  // если фильтр пустой, ничего не введено, то тупое присвоение 
  // ему "WHERE" - даст ошибку. поэтому опять проверям.
  if WhereClause <> '' then
    WhereClause := ' WHERE ' + WhereClause;
  // при изменении SQL квери закрывается автоматом, поэтому закрывать 
  // её руками - смысла нет. сразу присваиваем то, что нам надо
  Query1.SQL.Text := SelectClause + WhereClause;
  // БАНЗАЙ!!!
  Query1.Active := TRUE;
end;

end.


(1) на самом деле, это сляпано на глазок, и это не лучший способ. лучше, если выставить TEdit'ам свойство Tag равным нужному индексу в массиве полей, и делать перебор всех контролов, проверять, что это едит, брать его тэг, и по тэгу получать имя поля.

единственный возможный глюк в этом коде - Багланд умудрились засунуть в таблицу поле с пробелом (!) в его имени. у меня лично не работает фильтр по Species Name, даже по "Sepices Name" не работает, я фиг его знает, как эти дятлы додумались до такого. так делать нельзя никогда smile

второй момент, у меня используется OR - т.е. если хоть одно из введённых юзверем значений совпадёт с нужным полем - то запись с этим полем отобразиться. но могут быть и другие условия, AND, например smile

успехов smile разберись с этим кодом и сделай по аналогии. 

Автор: Fast 22.4.2006, 01:18
Цитата(RooR @  21.4.2006,  17:34 Найти цитируемый пост)
оиск по всем полям, весь dbgrid очищается, какбудто конект проподает к adoconnection

Так может быть просто нету записей которые удовлетворяют условию!!!!!!!!!!
А вообще Select * From обычно делают через ADOdataset !!!
Попробуй так !!!
Код

procedure TForm5.Button6Click(Sender: TObject);
var
mFilter, nFilter, xFilter : String;
begin
With Form1 do
begin
ADOQuery1.Active := False;
ADOQuery1.SQL.Clear;
mFilter := 'Select * From BOOK Where ';
nFilter := '';
if Edit1.Text <> '' then
nFilter := nFilter + ' AND Издательство =#' + Edit1.Text + '#';
if Edit2.Text <> '' then
nFilter := nFilter + ' AND Название =#' + Edit2.Text + '#';
if Edit3.Text <> '' then
nFilter := nFilter + ' AND Автор =#' + Edit3.Text + '#';
if Edit4.Text <> '' then
nFilter := nFilter + ' AND [Шифр книги] =#' + Edit4.Text + '#';
Delete(nFilter,1,5);
xFilter := mFilter + nFilter;
ShowMessage(xFilter); // Это используется чтобы посмотреть как выглядет твой запрос ПОТОМ УДАЛИ!!!!
ADOQuery1.SQL.Text := xFilter;
ADOQuery1.ExecSQL;
end
end;


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

Автор: x77 22.4.2006, 01:33
Fast, у тебя всегда прошивается 'where', т.е. если юзверь ничего не выбрал, запрос будет выглядеть как 'select * from ... where' - и он всегда даст ошибку. там нужна проверка. 

Автор: Fast 22.4.2006, 01:59
Цитата(x77 @  22.4.2006,  01:33 Найти цитируемый пост)
Fast, у тебя всегда прошивается 'where', т.е. если юзверь ничего не выбрал, запрос будет выглядеть как 'select * from ... where' - и он всегда даст ошибку. там нужна проверка. 

А да что то я не обратив внимание  smile 
Щас исправлю  smile

Добавлено @ 02:08 
Вот так  smile 

Код

procedure TForm5.Button6Click(Sender: TObject);
var
mFilter, nFilter, xFilter : String;
begin
With Form1 do
begin
ADOQuery1.Active := False;
ADOQuery1.SQL.Clear;
mFilter := 'Select * From BOOK Where ';
nFilter := '';
if Edit1.Text <> '' then
nFilter := nFilter + ' AND Издательство =#' + Edit1.Text + '#';
if Edit2.Text <> '' then
nFilter := nFilter + ' AND Название =#' + Edit2.Text + '#';
if Edit3.Text <> '' then
nFilter := nFilter + ' AND Автор =#' + Edit3.Text + '#';
if Edit4.Text <> '' then
nFilter := nFilter + ' AND [Шифр книги] =#' + Edit4.Text + '#';
if nFilter := '' then                            // Если ничего не ввели !!!
ShowMessage('Вы неввели параметры запроса')
else
begin
Delete(nFilter,1,5);
xFilter := mFilter + nFilter;
ShowMessage(xFilter); // Это используется чтобы посмотреть как выглядет твой запрос ПОТОМ УДАЛИ!!!!
ADOQuery1.SQL.Text := xFilter;
ADOQuery1.ExecSQL;
end;
end;
end;
  

Автор: Palladin 24.4.2006, 01:32
Блин всёровно не пашет, ошибки за ошибками, весь день убил на это, чёто не выходит, может у когонить есть ссылка на материал по данному поводу 

Автор: Fast 24.4.2006, 01:40
А тебе обязательно использовать SQL ?

Добавлено @ 01:41 
Или скинь сейчас сорцы я посмотрю  smile  

Автор: TheCetus 24.4.2006, 08:30
Fast, в 10-й строке лучше написать следующим образом:
mFilter := 'Select * From BOOK Where 1=1 ';
тогда если пользователь не введет ни одного условия ошибки вылетать не будет...
в твоем же случае запрос  примет вид
'Select * From BOOK Where ' , что несомненно приведет к ошибке 

Автор: Fast 24.4.2006, 13:18
Цитата(TheCetus @  24.4.2006,  08:30 Найти цитируемый пост)
Fast, в 10-й строке лучше написать следующим образом:
mFilter := 'Select * From BOOK Where 1=1 ';
тогда если пользователь не введет ни одного условия ошибки вылетать не будет...
в твоем же случае запрос  примет вид
'Select * From BOOK Where ' , что несомненно приведет к ошибке  


Код

if nFilter := '' then                           
ShowMessage('Вы неввели параметры запроса')
else


Я это не просто так написал  smile  

Автор: Palladin 25.4.2006, 01:26
Мне не обязательсно SQL, я пробовал через фильтр, по одному полю ищет прекрасно, а вот когда по нескольким то фигня какаята, нехочет искать, то отобразит не то что нужно, то вообще всё уберёт и т.п.  Я готов выслушать любые предложения по поводу поиска smile  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)