【问题标题】:Using LIKE and '%' in an ADO dataset filter在 ADO 数据集过滤器中使用 LIKE 和 '%'
【发布时间】:2014-06-19 19:40:14
【问题描述】:

尝试在 Delphi XE2 中对 ADO 数据集应用过滤器时遇到问题 ...

Filter := ' [Name] like ''%john'' ';

引发异常:

Project Test.exe raised exception class EOleException with message 
'Arguments are of the wrong type, are out of acceptable range, 
or are in conflict with one another'. Process stopped. 

但使用时:

Filter := ' [Name] like ''john%'' '

效果很好!

为什么?

【问题讨论】:

  • 所以实际不起作用的代码是Filter := '[Name] like ''%john'''?
  • 你试过用 * 代替 % 吗?
  • 我不知道这是否适用于最近的 ADO 版本,也不知道 topicstarter 是否使用当代 ADO。 请注意,不支持在 LIKE 子句的字符串条件中使用通配符作为第一个字符。您只能使用通配符作为 ADO 过滤器的 LIKE 原因条件的结束字符,或同时作为开始和结束字符。 support.microsoft.com/kb/181487support.microsoft.com/kb/226119
  • 也许您可以将 ADO/MDAC 更新到 2.8sp1 版本。也许您可以使用一些特定于数据服务器的技巧,例如将名称的最后 4 个字母复制到单独的列中。也许您可以将该条件移动到 SQL SELECT WHERE 子句中并重新打开查询。也许有像 TBDEDataSet.OnFilterRecord 这样的事件处理程序,您可以在 Delphi 中计算您想要的所有内容。或者你什么也做不了。

标签: delphi ado


【解决方案1】:

操作员只能是以下之一: = = 喜欢 如果使用 LIKE 运算符,还可以使用 * 或 % 通配符作为字符串中的最后一个字符或作为字符串中的第一个和最后一个字符。

http://www.devguru.com/technologies/ado/quickref/recordset_filter.html

您可以在事件 OnFilterRecord 上捕获过滤器:

procedure TForm1.ADODataSet1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
var
  iPos: Integer;
begin
  iPos:= pos('john',ADODataSet1name.AsString);
  if (iPos>0) and
     (iPos = length(ADODataSet1name.AsString)-3) then
  begin
    Accept:= True;
  end
  else
  begin
    Accept:= False;
  end;
end;

function TForm1.IsLastCriteria(AText: String): Boolean;
var
  iPos: Integer;
begin
  iPos:= pos(AText,ADODataSet1name.AsString);
  Result:= (iPos>0) and
           (iPos = length(ADODataSet1name.AsString)-length(AText)-1);
end;

procedure TForm1.ADODataSet1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
  Accept:= IsLastCriteria('john');
end;

【讨论】:

  • +1。顺便说一句,Accept := (iPos>0) and ... 恕我直言,没有if 的阅读效果更好。
  • @kobik:是的,我知道。但我喜欢 if then ... :-)
【解决方案2】:

作为。我仍然要求您阅读 http://www.catb.org/esr/faqs/smart-questions.html#beprecise 并相应地描述您的环境。

  • 什么是数据库服务器?
  • MDAC/ADO 组件是什么版本?
  • 查询是什么?
  • 什么是 SQL 中的 Name 列类型?

你正在“提升”cmets,这很好。但你不回答问题。这并不好。我们不是 ESPers,我们无法读懂你的想法。

我在上面的 cmets 中为您提供了一些建议。你试过了吗?他们工作了吗?引用他们:

  1. 也许您可以将 ADO/MDAC 更新到 2.8sp1 版本。参考的 MSDN 知识库文章被告知适用于 MDAC 最高 2.7 版本。也许 2.8sp1 不再有这个限制了。
  2. 也许您可以使用一些特定于数据服务器的技巧,例如将名称的最后 4 个字母复制到单独的列中。
  3. 也许您可以将该条件移动到 SQL SELECT WHERE 子句中并重新打开查询。
  4. 也许有像 TBDEDataSet.OnFilterRecord 这样的事件处理程序

有 4 种解决方法,您要么没有尝试过,要么没有报告结果。不好看。

  • 想法 #1 不言自明
  • @SertacAkyuz 尽其所能详细说明了想法 #3,但缺少有关您的程序的信息。
  • @Ravaut123 详细介绍了想法 #4
  • 想法 #2 概述如下

假设您的“ADO 数据库”由 Microsoft Access 支持,并且根据 http://www.databasedev.co.uk/access-sql-string-functions.html ... 或者使用 MS SQL 并根据http://msdn.microsoft.com/en-us/library/ms177532.aspx ... 或者……

Query.SQL.Text := 'select Right(Name, 4) as name_tail, * from table where ...'

查看添加到查询的额外列! 4 是“john”的长度。

对于这样的查询,以下过滤条件是等价的:

  • 过滤器 := ' [Name] like ''%john'' ';
  • 过滤器 := ' [name_tail] = ''john'' ';

但是,如果在某些行上 Name 列短于 4 个字母,我不知道 RIGHT 函数会做什么。也许它会截断结果,或者可能会抛出错误并中止查询。后者可能 - 取决于真实数据 - 可能可以通过用空格填充到 4 长度来缓解,比如

LTrim(Right('    ' || Name, 4)) as name_tail

这是由你来测试的,因为只有你知道你的环境的细节。

【讨论】:

  • 哦!谢谢,我很抱歉:(在Delphi中我使用ADOTable并且这个组件不支持SQL命令。所以我改为ADOQuery组件并使用SQL命令来做这个过滤器。--------你的想法很完美并且完整,但是他们需要 SQL 命令并且该组件会支持。对不起!我的英语很差。
【解决方案3】:

cmets 中提到了这个问题的最简单答案。 如果您使用星号而不是百分号,一切都会很好 Filter := ' [Name] like ''*john'' ';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-24
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多