FireDAC 中 TEdit 搜索功能的通配符格式是什么 Delphi

What is the wildcards format for TEdit search function in FireDAC Delphi

这是我使用 TEdit 组件搜索数据的代码,该组件使用参数触发 TFDQuery:

qryItems.ParamByName('searches').AsString := Format('%%%s%%',[edtSearch.Text]);

如果我删除通配符 (Format('%%%s%%')) 格式,它会起作用。通配符将帮助我过滤查询。

我喜欢代码,它干净、简单、直接。但是,我仍然不确定它是否正确——它没有返回任何东西!

我的问题是: 上面的代码是否适用于 TEdit.OnChangeTracking 事件的查询过滤?否则,正确的做法是什么?

更新 1: 这是来自 TFDQuery Editor 的代码:

SELECT category.name AS category, item.name, item.description
FROM item
JOIN category ON item.category_id = category.list_id
WHERE item.description LIKE :searches
ORDER BY item.sellable
LIMIT 100

现在,我试图在运行时从这段代码访问它,但它不起作用:

qryItems.ParamByName('searches').AsString := Format('%%%s%%',[edtSearch.Text]);

我认为这里的罪魁祸首是这段代码 Format('%%%s%%',[edtSearch.Text]),我没听对。

一个简短的回答是您希望以这样的参数分配结束:

  FDQuery1.Params[0].AsString := '%a%';
  FDQuery1.Open();

假设您要在 LIKE 表达式中匹配的值只是字母 a。或者,如果你想使用 Format,你可以这样做:

  FDQuery1.Params[0].AsString := Format('%%%s%%', [edFilter.Text]);

连续出现三个哈希符号的原因是表达式 Format 中的第一个 'escapes' 和第二个计算,第三个紧接在 's' 之前与它作为 Format 构造其结果的字符串的占位符。

但是,鉴于您对使用数据集和过滤并不完全熟悉, 我认为你至少在两个方面给自己造成了不必要的困难:

  • FMX + LiveBindings 并非完全没有错误,并且有一些怪癖可能会妨碍您。

  • 使用 LIKE 运算符的语法使用井号 (#),与使用冲突 用于解析 Format 函数中的参数的哈希符号。这尤其可以是 极度令人困惑,尤其是当您试图获得语法上有效的 LIKE 表达式,无论是包含在您的查询使用的 Sql 中还是包含在“本地过滤器”中, 即使用 FDQuery 的 Filter + Filtered 属性的一个。

所以,我要提出一个最初可能不受欢迎的建议, 这是做你的探索 在 VCL 应用程序中进行过滤之类的事情,例如下面的应用程序。设置只需几分钟, 但与 试图在正在开发的 FMX + LiveBinding 应用程序中正确使用它。方法如下:

  1. 创建一个新的 VCL 应用程序并将这些组件添加到其中。
    FDConnection1: TFDConnection;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    FDQuery1: TFDQuery;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    DataSource1: TDataSource;
    edFilter: TEdit;
    btnLocalFilter: TButton;
    btnSqlFilter: TButton;
  1. 将下面的代码添加到表单的文件中。

  2. 在行上放置一个调试器断点

case FilterMode of

并探索应用更改 edFilter 控件内容的行为 然后单击两个按钮,一旦您将代码调整为您拥有的数据 可用的。我的使用作者的 table,我不记得从哪里得到的 但也许它来自 Sql-Server.

的 Pubs 示例数据库

该应用程序显示 - 正如我确定您已经收集到的那样 - 您可以过滤显示的数据 通过您的应用程序在服务器端通过更改 Sql 用于检索数据或在客户端通过使用 FDQuery 的 Filter 属性。这样你就可以很容易地看到发生了什么,服务器端的 Sql 过滤是通过将 edFilter.Text 的内容与 Sql 的其余部分,但在现实生活中,你应该 永远不要 这样做,因为 它暴露于 Sql Injection exploit.

代码

type
  TFilterMode = (fmLocal, fmSql);

type
  TForm1 = class(TForm)
  [...]
  public
    { Public declarations }
    FilterMode : TFilterMode;
  end;
[...]
const
      sOrderBy = ' order by lastname, forename';
      sSql = 'select * from authors';
      sFilteredSql = sSql + ' where lastname like  :lastname%';
      sLocalFilter = 'lastname like ''%%s%%''';

procedure TForm1.OpenFDQuery;
var
  S : String;
begin
  if FDQuery1.Active then FDQuery1.Close;
  FDQuery1.Params.Clear;
  FDQuery1.Filter := '';
  FDQuery1.Filtered := True;
  case FilterMode of
    fmSql : begin
      FDQuery1.Sql.Text := '';
      //  WARNING - don't do this for real - risk of Sql Injection exploit
      //  use a parameterised query instead - see http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_Parameters_in_Queries
      S := 'select * from authors where lastname like ''%' + edFilter.Text + '%''';
      FDQuery1.Sql.Text := S;
    end;
    fmLocal : begin
      FDQuery1.Sql.Text := sSql + sOrderBy;
      S := 'lastname like ''%' + edFilter.Text + '%''';
      FDQuery1.Filter := S;
      FDQuery1.Filtered := True;
    end;
  end;

  FDQuery1.Open;
end;

procedure TForm1.ApplySqlFilter;
begin
  FilterMode := fmLocal;
  OpenFDQuery;
end;

procedure TForm1.ApplyLocalFilter;
begin
  FilterMode := fmLocal;
  OpenFDQuery;
end;

procedure TForm1.btnLocalFilterClick(Sender: TObject);
begin
  ApplyLocalFilter;
end;

procedure TForm1.btnSqlFilterClick(Sender: TObject);
begin
  ApplySqlFilter;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  edFilter.Text := 'a';
end;