delphi - AdoDB 对合并列进行过滤

标签 delphi ms-access ado tadotable

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

我尝试根据用户输入过滤 AdoTable。有 3 个重要的列:name、surname 和 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 等名字,效果会很差..)

或者,我可以重写整个程序以使用查询而不是表,但我真的不想这样做(这也意味着每次用户更改 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”等。

最佳答案

下面的代码可以与 Access Delphi dbdemos.mdb 数据库中的 employee 表的 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 层 Access 该表,并且 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;

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

关于delphi - AdoDB 对合并列进行过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41931948/

相关文章:

sql - 当列名是数字时,使用 VB.NET 中的 ADO 查询 Excel

Delphi - idFTP获取当前目录

delphi - Move 上的浮点运算无效?

windows - 全局信号量忽略本地信号量

mysql - 将 Access SQL 内部联接查询转换为 mySQL 查询时出现问题

sql - 构造 SQL 查询以使用另一个表中的数据填充一个表

ms-access - 为什么我的 Access 数据库在我从另一个进程中读取时不是最新的?

c++ - ADODB/C++ : What does "Execute" return when single value is returned?

Delphi XE 构建事件.. 全局?

database - 无法用数据填充 OleDbDataAdapter