【问题标题】:Search database table by record fields and display record on cxgrid按记录字段搜索数据库表并在 cxgrid 上显示记录
【发布时间】:2026-02-19 03:20:02
【问题描述】:

允许用户通过在 tedit 框中键入文本并单击按钮来搜索数据库表中记录的最佳方法是什么,然后结果将显示在 tcxgrid 上。

我有一个 tadquery/datasource,它正在查看一个包含各种字段的表。如果用户能够在表格中搜索多个字段,那就太好了。

谢谢。

【问题讨论】:

  • 您必须接受多个字段名称和值,并使用TDataSet.Locate。如何设计界面取决于您和您的具体要求。
  • 我已经完成了下面的代码但是得到了错误信息..'variant or safe array index out of bounds'。
  • 你不能那样做。您说过有两列(“Customer_Code”和“Name”),因此数组必须有两个元素(索引 0 = Customer_Code 和索引 1 = 名称)。您只需将一个元素放入数组中。
  • 很抱歉,您能举个例子吗?这就是我目前所拥有的... Locate('customer_code;name',(editSearch.Text),[loPartialKey,loCaseInsensitive]);
  • 你可以使用 TcxFiltercontrol 或 TcxDbFilterControl

标签: delphi delphi-xe2 sybase-asa tcxgrid


【解决方案1】:

您可以为此使用TDataSet.Locate,传递以分号分隔的字段名称列表和要匹配的常量字段值数组。通常,这很容易:

DataSet.Locate('Field1;Field2', ['Value1', 'Value2'], [loPartialKey]);

但是,由于您不提前知道有多少列,您需要以不同方式处理数组,使用 VarArrayCreate 并分别设置每个数组值。

这个例子从Edit1(用分号分隔)中获取字段列表,从Edit2(同样,用分号分隔,字符串值被'字符包围,所以它们是正确地包含在数组中)。它将Edit1 的内容拆分为一个数组以找出有多少元素,分配一个适当大小的变量数组,填充它,然后将字段列表和值数组都传递给TDataSet.Locate。已使用Edit1.Text := 'Customer_No;Name';Edit2.Text := '1;''Smith'''; 进行了测试。

procedure TForm5.Button1Click(Sender: TObject);
var
  Temp: string;
  Fields: TArray<string>;
  Vals: TArray<string>;
  FieldValues: Variant;
  i: Integer;
begin
  // Grab a copy so we can split it into separate values
  Temp := Edit1.Text;
  Fields := Temp.Split([';']);

  // Create the array of variants to hold the field values    
  FieldValues := VarArrayCreate([0, High(Fields)], VarVariant);

  // Temporary copy to allow splitting into individual values      
  Temp := Edit2.Text;
  Vals := Temp.Split([';']);
  for i := 0 to High(Fields) do
    FieldValues[i] := Vals[i];

  // Use original field list from Edit1 for the Locate operation
  DataSet1.Locate(Edit1.Text, FieldValues, [loCaseInsensitive]);
end;

对于包含TStringHelper 之前的Delphi 版本(例如您正在使用的XE2,只需将TypesStrUtils 添加到您的uses 子句并使用SplitStringTStringDynArray 代替:

procedure TForm5.Button1Click(Sender: TObject);
var
  Temp: string;
  Fields: TStringDynArray;
  Vals: TStringDynArray;
  FieldValues: Variant;
  i: Integer;

begin
  Temp := Edit1.Text;
  Fields := SplitString(Temp, ';');

  FieldValues := VarArrayCreate([0, Length(Fields)], VarVariant);
  Temp := Edit2.Text;
  Vals := SplitString(Temp, ';');
  for i := 0 to High(Fields) do
    FieldValues[i] := Vals[i];

  DataSet1.Locate(Temp, FieldValues, [loCaseInsensitive]);
end;

【讨论】:

  • 对不起,我才看到这个,你可以忽略上面的评论
  • .Split ?...Delphi 无法将其识别为属性。
  • 对不起,我应该提到我使用的是 Delphi XE2
  • 您确实做到了(在您的标签中)。更新后还包括早期版本的版本。
【解决方案2】:

我会使用数据源查询,并在按钮的 onclick 事件中,使用 WHERE 子句重新加载查询

Query1.SQL.Add('WHERE Name LIKE :P1 OR Postcode LIKE :P2 OR Town LIKE :P3');

并添加参数

Query1.SQL.Parameters.ParamByName('P1').Value := '%' + Edit1.Text + '%';
Query1.SQL.Parameters.ParamByName('P2').Value := '%' + Edit1.Text + '%';
Query1.SQL.Parameters.ParamByName('P3').Value := '%' + Edit1.Text + '%';

使用 '%' 允许搜索字符串中的任何位置作为选项。

Query1.Open;

我已经多次使用这种技术了。

【讨论】: