2

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

我试图根据用户输入过滤 AdoTable。有 3 个重要列:姓名、姓氏和 ID。我想出了类似这样的临时解决方案:

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

它确实有效,但它并没有完全按照我想要的那样做......(在搜索 name 和 surename 时,它​​不会找到任何东西,因为它只在一列中显示)。所以后来我把我的代码修改成这样:

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 等名字,它会很糟糕。)

或者,我可以重写整个程序以使用查询而不是表,但我真的不想这样做(这也意味着我将获得新的 recordSet 每次用户都会更改 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%'

请注意,可能有“hn Smith”而不是“John Smith”,因此它也会找到“Kahn Smithers”等。

4

2 回答 2

1

employee下面的代码适用于访问Delphidbdemos.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;

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

于 2017-01-30T12:32:07.917 回答
1

我发现了这个:使用 LIKE 语句进行过滤并使用接受的答案,它工作得很好。(由于问题完全不同,无法尽快找到它)

在表过滤器上:

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;

谢谢你的时间......我会把它留在这里..我认为最终有人可能需要它

于 2017-01-30T14:12:02.633 回答