合并列上的 AdoDB 过滤器
AdoDB filter on merged columns
所以我有一个 AdoTable 连接到数据库 (mdb) 和使用它的 DataSource。此数据源由 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;
它确实有效,但它并没有完全按照我想要的方式执行...(在搜索 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 等名字,效果会很差。)
或者,我可以重写整个程序以使用查询而不是表,但我真的不想这样做(这也意味着我将获得新的记录集,每次用户将更改 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' 等
下面的代码适用于 AdoTable,它访问 Delphi dbdemos.mdb
数据库中的 employee
table。我的 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-specific 语法。您正在通过 ADO 层访问 table ,并且 AFAIK 期望使用与您使用的语法相同的语法,例如对于 Sql 服务器 back-end.
从您的评论来看,您似乎想要涵盖用户在您的 Edit1.Text 中键入名字片段后跟 space 片段或片段的情况姓。以下将执行此操作:
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 是为了忽略用户可能使用的任何大写。
我发现了这个:Using LIKE statement for filtering 并使用了公认的答案,它工作得很好。 (无法尽快找到它,因为问题完全不同)
在 table 过滤器上:
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;
谢谢你的时间...我会把它留在这里..我想最终有人会需要它
所以我有一个 AdoTable 连接到数据库 (mdb) 和使用它的 DataSource。此数据源由 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;
它确实有效,但它并没有完全按照我想要的方式执行...(在搜索 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 等名字,效果会很差。)
或者,我可以重写整个程序以使用查询而不是表,但我真的不想这样做(这也意味着我将获得新的记录集,每次用户将更改 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' 等
下面的代码适用于 AdoTable,它访问 Delphi dbdemos.mdb
数据库中的 employee
table。我的 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-specific 语法。您正在通过 ADO 层访问 table ,并且 AFAIK 期望使用与您使用的语法相同的语法,例如对于 Sql 服务器 back-end.
从您的评论来看,您似乎想要涵盖用户在您的 Edit1.Text 中键入名字片段后跟 space 片段或片段的情况姓。以下将执行此操作:
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 是为了忽略用户可能使用的任何大写。
我发现了这个:Using LIKE statement for filtering 并使用了公认的答案,它工作得很好。 (无法尽快找到它,因为问题完全不同)
在 table 过滤器上:
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;
谢谢你的时间...我会把它留在这里..我想最终有人会需要它