2

Delphi 似乎不喜欢多字段索引。

我如何对一个表进行物理排序,以便最终得到一个具有所需顺序的行的表?

例子:

我的表.dbf

Field   Field-Name   Field-Type   Size
  0     Payer        Character     35
  1     Payee        Character     35
  2     PayDate      Date
  3     Amount       Currency

我需要生成一个按“Payee”+“Payer”字母顺序排序的表格

当我尝试使用“Payee+Payer”索引时,出现错误:

“字段索引超出范围”

4

5 回答 5

4

索引字段名称需要用分号分隔,而不是加号。尝试一下,它应该可以工作。

于 2010-02-23T14:36:13.807 回答
3

好的,让我们尝试下订单。

首先,不建议对表格进行物理排序。事实上,大多数 RDBMS 甚至都没有为您提供此功能。通常,为了不强制进行全表扫描(有时称为自然扫描) ,会在他认为将对表进行排序/搜索的表字段上创建索引。

如您所见,对表进行排序的第一步通常是创建索引。这是一个单独的步骤,它只完成一次,通常是在“设计时”。在此之后,数据库引擎将自动更新索引。

索引创建由您(开发人员)使用(通常)不是 Delphi(或任何其他开发工具),而是您的 RDBMS 的管理工具(您在创建表时使用的相同工具)完成索引创建。

如果您的“数据库引擎”实际上是一个 Delphi 内存数据集 (TClientDataSet),那么您将转到IndexDefs属性,打开它,添加一个新索引并相应地在那里设置属性。我们讨论中有趣的性质是Fields。将其设置为Payee;Payer。也设置Name为例如。“idx收款人”。如果您使用其他 TDataSet 后代,请查阅您的数据库引擎的文档或在 SO.com 上提出其他问题,提供详细信息。

现在,要使用索引。(IOW,如您所说,对表格进行排序)。在您的程序中(在设计时或在运行时)在您的“表”中设置IndexName为“idxPayee”或您提供或设置IndexFieldNames为的任何其他有效名称Payee;Payer

再次注意,上面是一个基于 TClientDataSet 的例子。您必须从上面保留的内容(如果您不使用它)是您必须有一个已经创建的索引才能使用它

另外,要回答您的问题,是的,有一些“表”类型(Delphi 术语中的 TDataSet 后代)支持排序,无论是通过Sort方法(或类似方法)还是通过SortFields属性。

但是现在通常当使用 SQL 后端时,首选的解决方案是使用相应的管理工具创建索引,然后发出(使用 Delphi)一个SELECT * FROM myTable ORDER BY Field1.

高温高压

于 2010-02-23T17:08:28.193 回答
1

如果您仍在使用 BDE,则可以使用 BDE API 对 DBF 表进行物理排序:

uses
  DbiProcs, DbiTypes, DBIErrs;

procedure SortTable(Table: TTable; const FieldNums: array of Word; CaseInsensitive: Boolean = False; Descending: Boolean = False);
var
  DBHandle: hDBIDb;
  RecordCount: Integer;
  Order: SORTOrder;
begin
  if Length(FieldNums) = 0 then
    Exit;

  Table.Open;
  RecordCount := Table.RecordCount;
  if RecordCount = 0 then
    Exit;
  DBHandle := Table.DBHandle;
  Table.Close;

  if Descending then
    Order := sortDESCEND
  else
    Order := sortASCEND;

  Check(DbiSortTable(DBHandle, PAnsiChar(Table.TableName), nil, nil, nil, nil, nil,
    Length(FieldNums), @FieldNums[0], @CaseInsensitive, @Order, nil, False, nil, RecordCount));
end;

例如,在您的情况下:

  SortTable(Table1, [2, 1]); // sort by Payee, Payer
于 2010-02-25T08:49:39.663 回答
0

您可以在一次调用中使用 TTable.AddIndex 方法在表上创建索引。这将在您读取数据时对数据进行排序,也就是说,如果您通过将 TTable.IndexName 属性设置为新索引来使用新索引。这是一个例子:

xTable.AddIndex('NewIndex','Field1;Field2',[ixCaseInsensitive]);
xTable.IndexName := 'NewIndex';
// Read the table from top to bottom
xTable.First;
while not xTable.EOF do begin
  ..
  xTable.Next;
end;
于 2010-02-28T08:17:13.850 回答
0

无法检查,但尝试 IndexFieldNames = "Payee, Payer"。
这两个字段的肯定索引应该存在。

于 2010-02-23T14:34:15.497 回答