如何使用 like 子句和变音符号过滤数据集中的字符串字段?
How can I filter a string field in a dataset with a like clause and an umlaut?
尽管有一些关于数据集过滤的 documentation,但仅概述了语法细节。在我的应用程序中,我想使用数据集过滤器来过滤人名。通常这工作得非常快,但我偶然发现了一个小问题过滤,例如 TClientDataset
。如何为变音符号添加类似过滤器?表达式
[X] LIKE 'Ö%'
(for a given field 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
.
对 Unicode 代码使用 ftWideString data type to create a TWideStringField field instead of ftString, which internally creates a TStringField field. TStringField is for ANSI strings whilst TWideStringField。这样做,否则你会丢失数据。
访问TWideStringField value use AsWideString属性。我在 D 2009 中进行了快速测试,当我尝试过滤数据集时,我得到了这个:
First chance exception at 94845D. 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 单元来改变)。
尽管有一些关于数据集过滤的 documentation,但仅概述了语法细节。在我的应用程序中,我想使用数据集过滤器来过滤人名。通常这工作得非常快,但我偶然发现了一个小问题过滤,例如 TClientDataset
。如何为变音符号添加类似过滤器?表达式
[X] LIKE 'Ö%'
(for a given field 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
.
对 Unicode 代码使用 ftWideString data type to create a TWideStringField field instead of ftString, which internally creates a TStringField field. TStringField is for ANSI strings whilst TWideStringField。这样做,否则你会丢失数据。
访问TWideStringField value use AsWideString属性。我在 D 2009 中进行了快速测试,当我尝试过滤数据集时,我得到了这个:
First chance exception at 94845D. 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 单元来改变)。