delphi - 如何使用 like 子句和元音变音来过滤数据集中的字符串字段?

标签 delphi sql-like delphi-10.1-berlin tclientdataset client-side-data

虽然有一些documentation关于数据集过滤,仅概述语法细节。在我的应用程序中,我想使用数据集过滤器来过滤人名。通常情况下,这工作得非常快,但我偶然发现了一个过滤小问题,例如 TClientDataset。如何为变音符号添加类似过滤器?表达式

[X] LIKE 'Ö%'

(对于给定字段X)不起作用(与表达式[X] LIKE 'A%'相反)。这只是一个错误还是我需要在某处设置字符集/编码?

最小示例:

procedure TForm1.FormCreate(Sender: TObject);
var
  LField: TFieldDef;
  LCDs: TClientDataSet;
const
  SAMPLE_CHAR: string = 'Ö';
begin
  LCds := TClientDataSet.Create(Self);
  LField := LCds.FieldDefs.AddFieldDef();
  LField.DataType := ftString;
  LField.Size := 10;
  LField.Name := 'X';
  LCDs.CreateDataSet;
  LCDs.Append;
  LCDs.FieldByName('X').AsString := SAMPLE_CHAR;
  LCDs.Post;

  ShowMessage(LCds.FieldByName('X').AsString);
  LCds.Filter := '[X] LIKE ' + QuotedStr(SAMPLE_CHAR + '%');
  LCds.Filtered := true;
  ShowMessage(LCds.FieldByName('X').AsString);
end;

第一个消息框显示Ö,而第二个消息框为空。如果将 SAMPLE_CHARÖ 更改为 A,两个消息框都会显示 A

最佳答案

使用ftWideString创建 TWideStringField 的数据类型字段而不是 ftString ,它在内部创建一个 TStringField field 。 TStringField用于 ANSI 字符串,而 TWideStringField对于 Unicode 的。这样做,否则你会丢失数据。

访问TWideStringField值(value)利用AsWideString属性(property)。我在 D 2009 中进行了快速测试,当我尝试过滤数据集时,我得到了以下结果:

First chance exception at $7594845D. Exception class EAccessViolation with message 'Access violation at address 4DB1E8D1 in module 'midas.dll'. Read of address 00FC0298'.

测试代码:

procedure TForm1.FormCreate(Sender: TObject);
var
  S: string;
  FieldDef: TFieldDef;
  MemTable: TClientDataSet;
begin
  S := 'Ŧĥε qùíçķ ƀřǭŵņ fôx ǰűmpεď ōvêŗ ţħě łáƶÿ ďơǥ';

  MemTable := TClientDataSet.Create(nil);
  try
    FieldDef := MemTable.FieldDefs.AddFieldDef;
    FieldDef.DataType := ftWideString;
    FieldDef.Size := 255;
    FieldDef.Name := 'MyField';

    MemTable.CreateDataSet;
    MemTable.Append;
    MemTable.FieldByName('MyField').AsWideString := S;
    MemTable.Post;

    ShowMessage(MemTable.FieldByName('MyField').AsWideString); { ← data lost }
    MemTable.Filter := '[MyField] LIKE ' + QuotedStr('%' + 'ǰűmpεď' + '%');
    MemTable.Filtered := True; { ← access violation }
    ShowMessage(MemTable.FieldByName('MyField').AsWideString);
  finally
    MemTable.Free;
  end;
end;

我希望它与您的 Delphi 版本无关,但如果可以的话,我仍然更喜欢使用 FireDAC。您可以对 Unicode 字符串执行相同的操作(您的代码将通过用 TFDMemTable 替换 TClientDataSet 并添加 FireDAC 单元来更改)。

关于delphi - 如何使用 like 子句和元音变音来过滤数据集中的字符串字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45338758/

相关文章:

ios - 如何为可以通过照片库官方 iOS (Delphi/Firemonkey) 访问的图像创建自己的 App 文件夹

delphi - 关于德尔福之翼 (ORM)

mysql - "Merge"Mysql中的IN和LIKE操作符

mysql - SQL 查询结果如何用于另一个查询的 LIKE 条件?

sql - Golang 中的跨数据库准备好的语句绑定(bind)(like 和 where in)

delphi - 类运算符 - 区分大小写是设计原因还是缺陷?

Delphi XE2 HTTPRIO 无法检索服务/端口的 URL 端点

delphi - 如何发现我的服务的依赖项是什么?

delphi - GraphicEx 与 Delphi 10.1 Berlin

delphi - 将基数类型转换为单数