如何转到ado.locate(Delphi)结果中的最后一条记录

0 delphi ado

我通过以下代码找到了一些记录:

ADOQuery1.Locate('field1',ADOQuery2.FieldByName('field2').Value,[])  
Run Code Online (Sandbox Code Playgroud)

如何进入最后一条记录?

Dis*_*ned 6

你有很多选择.最好的取决于你在问题中没有提到的很多考虑因素.我将提供一个非常简短的概述,以避免这种情况变得"过于宽泛".您可以自己做出选择并弄清楚细节.如果您遇到困难,可以提出一个更具体的新问题.

运用 Locate

涉及的解决方案Locate唯一的,如果你的数据集是可行的排序由你正在寻找在同一个领域.

显然,您的搜索值不是唯一键.所以我猜你正在尝试找到与其他唯一字段排序的数据中匹配搜索关键字的最后一行.(否则,最后的概念毫无意义.)

所以这很可能不适合你; 除非您的数据按搜索字段的复合键排序,后跟唯一键.

方法很简单:向前导航,直到找到搜索值不匹配的行,然后返回1行.

if not DataSet.Locate(SearchField, SearchValue, []) then
  { handle not found case as desired }
else
begin
  while (not DataSet.Eof) and (DataSet.FieldByName(SearchField).Value = SearchValue) do
    DataSet.Next;

  { Watch out for case that last row in dataset matches search value }
  if (DataSet.FieldByName(SearchField).Value <> SearchValue) then
    DataSet.Prior;
end;
Run Code Online (Sandbox Code Playgroud)

实施自己的搜索

这是直截了当的,并将永远有效.但它效率低,具有O(n)复杂度.因此不建议使用大型数据集.

DataSet.Last;
while (not DataSet.Bof) and (DataSet.FieldByName(SearchField).Value <> SearchValue) do
  DataSet.Prior;
Run Code Online (Sandbox Code Playgroud)

注意:为了镜像Locate它的行为,建议增强此方法来处理根本找不到匹配的情况.在这种情况下,不应该无意中更改活动记录作为搜索的副作用.

使用过滤

显然,此解决方案取决于过滤数据集是否适合其余代码.但这是一个相当简单的选择,并且超出了本答案范围的依赖因素,它可能比以前的选项更具性能.

DataSet.Filtered := False;
{ The next line may be a little tricky.
  Ensure the filter string is appropriate for the data-types involved. }
DataSet.Filter := '<string of the form SearchField = SearchValue>';
DataSet.Filtered := True;
DataSet.Last;
Run Code Online (Sandbox Code Playgroud)

请参阅Filter属性的文档.

注意:建议采取预防措施,防止冗余设置过滤器.

使用主 - 细节关系

包含此选项是因为您的问题代码表明SearchValue来自另一个数据集的活动记录.您正在使用ADO,因此您可以使用此选项.

DataSet.MasterSource := <Appropriate DataSource>;
DataSet.MasterFields := SearchField;
DataSet.Last;
Run Code Online (Sandbox Code Playgroud)

请参阅有关主从关系ADO MasterFields的文档.

将工作卸载到RDBMS

最后,值得考虑使用存储过程直接从数据库中获取所需信息.优点是服务器可以利用可用的索引,并有可能提供最高性能的选项.但是,很多时候,很大程度上取决于您的申请的细节.

沿着以下行的查询可以构成存储过程的基础.

select  MAX(UniqueField) as RowKey
from    Table
where   SearchField = SearchValue
Run Code Online (Sandbox Code Playgroud)

然后调用存储过程,并使用其结果查找所需的行.

DataSet.Locate(UniqueField, RowKey, []);
Run Code Online (Sandbox Code Playgroud)

注意:NULL如果不存在具有SearchValue的行,请不要忘记返回存储过程.


一般免责声明

以上所有代码都非常简短,仅供说明之用.在许多情况下,强大的实现需要额外的代码.
例如,可能需要DisableControls再次启用它们.

注意:如上所述,了解数据集中数据的实际排序非常重要.如果不考虑这一点,可能会导致行为不正确.如果您的数据集未按UniqueKey排序,即使最后一个选项也可能表现出比预期更差的性能.