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

问题描述 投票:0回答:2

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

ADOQuery1.Locate('field1',ADOQuery2.FieldByName('field2').Value,[])  

如何进入最后一条记录?

delphi ado
2个回答
6
投票

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

Using 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;

Implement your own search

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

DataSet.Last;
while (not DataSet.Bof) and (DataSet.FieldByName(SearchField).Value <> SearchValue) do
  DataSet.Prior;

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

Use filtering

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

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;

请参阅Filter属性的文档。

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

Use a master-detail relationship

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

DataSet.MasterSource := <Appropriate DataSource>;
DataSet.MasterFields := SearchField;
DataSet.Last;

请参阅有关master-detail relationshipsADO MasterFields的文档。

Offload the work to the RDBMS

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

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

select  MAX(UniqueField) as RowKey
from    Table
where   SearchField = SearchValue

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

DataSet.Locate(UniqueField, RowKey, []);

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


General Disclaimer

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

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


0
投票

如果您的表具有自动增量标识字段,则可以执行此操作

adoquery1.sql.clear;
adoquery1.sql.add('select top 1 * from  yourtablename where field1=value1 and filed2=value2 order by yourAIcolums desc')
adoquery1.execsql;

value1和value2是你想要的值。将它们作为参数传递或者将它们放在命令文本中,这样你只得到你想要的行而不需要循环

© www.soinside.com 2019 - 2024. All rights reserved.