在 Delphi 中对表进行物理排序

发布于 2024-08-23 08:26:02 字数 418 浏览 9 评论 0原文

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

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

示例:

mytable.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”索引时,出现错误:

“字段索引超出范围”

Delphi does not seem to like multi-field indexes.

How do I physically sort a a table so that I wind up with a table that has the rows in the desired order?

Example:

mytable.dbf

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

I need to produce a table sorted alphabetically by "Payee"+"Payer"

When I tried using an index of "Payee+Payer", I got an error:

"Field Index out of range"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

樱娆 2024-08-30 08:26:02

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

The index field names need to be separated by semicolons, not plus symbols. Try that and it should work.

稀香 2024-08-30 08:26:02

好吧,让我们试着下一些订单。

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

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

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

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

现在,使用索引。 (IOW,正如你所说,对表格进行排序)。在您的程序中(无论是在设计时还是在运行时),将“Table”中的 IndexName 设置为“idxPayee”或您提供的任何其他有效名称,或将 IndexFieldNames 设置为收款人;付款人

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

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

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

华泰

Ok, let's try to put some order.

First, isn't advisable to physically sort a table. In fact the most RDBMS even don't provide you this feature. Usually, one, in order to not force a full table scan (it is called sometimes natural scan) creates indexes on the table fields on which he thinks that the table will be sorted / searched.

As you see, the first step in order to sort a table is usually index creation. This is a separate step, it is done once, usually at, let's say, "design time". After this, the DB engine will take care to automatically update the indexes.

The index creation is done by you (the developer) using (usually) not Delphi (or any other development tool) but the admin tool of your RDBMS (the same tool which you used when you created your table).

If your 'DB engine' is, in fact, a Delphi memory dataset (TClientDataSet) then you will go to IndexDefs property, open it, add a new index and set the properties there accordingly. The interesting property in our discussion is Fields. Set it to Payee;Payer. Set also the Name to eg. "idxPayee". If you use other TDataSet descendant, consult the docs of your DB engine or ask another question here on SO.com providing the details.

Now, to use the index. (IOW, to sort the table, as you say). In your program (either at design time either at run time) set in your 'Table' the IndexName to "idxPayee" or any other valid name you gave or set IndexFieldNames to Payee;Payer.

Note once again that the above is an example based on TClientDataSet. What you must retain from the above (if you don't use it) is that you must have an already created index in order to use it.

Also, to answer at your question, yes, there are some 'table' types (TDataSet descendants in Delphi terminology) which support sorting, either via a Sort method (or the like) either via a SortFields property.

But nowadays usually when one works with a SQL backend, the preferred solution is to create the indexes using the corresponding admin tool and then issue (using Delphi) an SELECT * FROM myTable ORDER BY Field1.

HTH

橪书 2024-08-30 08:26:02

如果您仍在使用 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

If you're still using BDE you can use the BDE API to physically sort the DBF table:

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;

for example, in your case:

  SortTable(Table1, [2, 1]); // sort by Payee, Payer
宫墨修音 2024-08-30 08:26:02

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

Cannot check, but try IndexFieldNames = "Payee, Payer".
Sure indexes by these 2 fields should exist.

哎呦我呸! 2024-08-30 08:26:02

您可以在一次调用中使用 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;

You can create an index on your table using the TTable.AddIndex method in one call. That will sort your data when you read it, that is if you use the new index by setting the TTable.IndexName property to the new index. Here's an example:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文