合并列上的AdoDB过滤器

时间:2017-01-30 08:55:30

标签: delphi ms-access ado tadotable

所以我有一个AdoTable连接到数据库(mdb)和使用它的DataSource。这个DataSource由DBGrid ...

使用

我尝试根据用户输入过滤AdoTable。有三个重要的列:名称,姓氏和ID。我想出了这样的临时解决方案:

AdoTable.filter:='surname like ' +
      QuotedStr('%'+edit1.text+'%')+' or name like ' +
      QuotedStr('%'+edit1.text+'%')+' or ID like ' +
      QuotedStr('%'+edit1.text+'%');
AdoTable.filtered:=true;

它确实有效,但它并没有完全按照我的意愿去做...(当搜索名称时,它确实找不到任何内容,因为它只在一列中查找)。 所以后来我将代码修改为:

AdoTable.filter:='surname & " " & name like ' +
      QuotedStr('%'+edit1.text+'%')+' or name & " " & surname like ' +
      QuotedStr('%'+edit1.text+'%')+' or ID like ' +
      QuotedStr('%'+edit1.text+'%');
AdoTable.filtered:=true;

现在这将是我想做的事情,但它会引发异常(EOleException:参数类型错误,超出可接受的范围,或者彼此冲突)。 这让我很吃惊,因为我认为它应该像sql命令中的where子句一样(并且它作为命令完美地运行)。

我尝试更换'&'用' +'。 我可以分割一个输入文本,但我不想这样做(如果你有像Robin van Persie,Ahmad ibn Hanbal等名字那么它会很糟糕。)

或者我可以重写整个程序来使用查询而不是表格,但我并不是真的想要这样做(这也意味着我将获得新的记录集EVERYTIME用户将改变edit1.text而不仅仅是过滤)。

有什么想法吗?

编辑: 所以有效的命令看起来像这样

select * from person where surname & " " & name like '%John Smith%' or name & " " & surname like '%John Smith%' or ID like '%John Smith%'

过滤器看起来像这样(并触发异常)

surname & " " & name like '%John Smith%' or name & " " & surname like '%John Smith%' or ID like '%John Smith%'

请注意,史密斯可能会出现这样的情况。而不是约翰史密斯'所以它也会找到Kahn Smithers'等

2 个答案:

答案 0 :(得分:1)

以下代码适用于访问Delphi employee数据库中dbdemos.mdb表的AdoTable。我的AdoConnection正在使用Microsoft Jet 4.0 OLE DB驱动程序。

procedure TForm1.Button1Click(Sender: TObject);
var
  FilterExpr : String;
begin
  AdoTable1.Filtered := not AdoTable1.Filtered;
  if AdoTable1.Filtered then begin
    FilterExpr := 'FirstName like ' + QuotedStr('%' + Edit1.Text + '%') + ' or LastName like ' + QuotedStr('%' + Edit1.Text + '%');
    AdoTable1.Filter := FilterExpr;
  end;
end;

我认为您的错误可能是使用了您提到的特定于Access的语法。您正在通过ADO层访问该表,并且AFAIK需要与您使用的语法相同的语法,例如:对于Sql Server后端。

从您的评论中,似乎您想要覆盖用户在Edit1.Text中键入名字的片段,然后是空格后跟片段或姓氏的情况。以下将这样做:

procedure TForm1.Button1Click(Sender: TObject);
var
  FilterExpr : String;
  P : Integer;
  S1,
  S2 : String;
begin
  AdoTable1.Filtered := not AdoTable1.Filtered;
  if AdoTable1.Filtered then begin
    P := Pos(' ', Trim(Edit1.Text));
    if P > 0 then begin
      S1 := Copy(Trim(Edit1.Text), 1, P - 1);
      S2 := Copy(Trim(Edit1.Text), P + 1, MaxInt);
      FilterExpr := '(FirstName like ' + QuotedStr('%' + S1 + '%') + ')';
      FilterExpr := FilterExpr + ' or (LastName like ' + QuotedStr('%' + S2 + '%') + ')';
    end
    else
      FilterExpr := 'FirstName like ' + QuotedStr('%' + Edit1.Text + '%') + ' or LastName like ' + QuotedStr('%' + Edit1.Text + '%');
    AdoTable1.Filter := FilterExpr;
  end;
end;

更新:如果您想允许用户输入类似

的内容 史密斯

然后您可以使用像这样的FilterRecord事件而不是上面的代码。

procedure TForm1.ADOTable1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
var
  S : String;
begin
  S := LowerCase(DataSet.FieldByName('FirstName').AsString + ' ' + DataSet.FieldByName('LastName').AsString);
  Accept := Pos(LowerCase(Edit1.Text), S) > 0; 
end;

显然,转换为LowerCase是为了忽略用户可能使用的任何大写字母。

答案 1 :(得分:1)

我发现了这个:Using LIKE statement for filtering并使用了接受的答案,它运作得很好。 (由于问题差异很大,因此无法及时找到它)

在表格过滤器上:

procedure TDataModule1.ADOTableFilterRecord(DataSet: TDataSet;
  var Accept: Boolean);
var
  nameSurname :string;
  surnameName :string;
begin
  nameSurname:= DataSet.FieldByName('name').AsString+' '+DataSet.FieldByName('surname').AsString;
  surnameName:= DataSet.FieldByName('surname').AsString+' '+DataSet.FieldByName('name').AsString;

  if assigned(MainForm) then
    Accept := (Pos(MainForm.edit1.Text, nameSurname) > 0)
  or (Pos(MainForm.edit1.Text, surnameName) > 0)
  or (Pos(MainForm.edit1.Text, DataSet.FieldByName('ID').AsString) > 0);
end;

编辑更改:

procedure TMainForm.edit1Change(Sender: TObject);
begin
    DataModule1.AdoTable.Filtered:=false;
    if edit1.Text<>'' then
      DataModule1.AdoTable.Filtered:=True;
end;

感谢您的时间......我会把它留在这里......我想最终有人可能需要它