2017-12-31 105 views
0

I befindet sich einige Datensätze durch diesen Code gehen:Wie kommt man zum letzten Datensatz in den Ergebnissen von ado.locate (Delphi)

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

Wie die letzte dieser Aufzeichnungen gehen?

+0

Mit einer Schleife, mit 'Next', bis Sie den ersten nicht übereinstimmenden Datensatz und dann ein' Prior' zu einem zurück zu erreichen. Vergessen Sie nicht, beim Looping auch nach "not Eof" zu suchen, um eine Endlosschleife zu vermeiden. Oder fügen Sie eine zweite Spalte zu Ihrem 'Locate'-Aufruf hinzu, um die Suche genauer zu machen, damit sie mit der Zeile übereinstimmt, die Sie wirklich finden möchten. –

+0

Tatsächlich besteht das Kriterium darin, einen bestimmten Wert in einem bestimmten Feld zu haben, dann ist der letzte hinzugefügte Datensatz das, was wir brauchen (d. H. Das letzte in den ado.locate-Ergebnissen). –

+1

"der letzte Datensatz hinzugefügt" Seien Sie vorsichtig, der letzte Datensatz, der dem Datensatz hinzugefügt wird, ist nicht unbedingt der am Ende Ihrer '.Next'-Schleife; ob dies der Fall ist oder nicht, hängt davon ab, ob der Datensatz nach Einfügereihenfolge geordnet ist. – MartynA

Antwort

6

Sie haben eine Reihe von Optionen. Das Beste hängt von einer ganzen Reihe von Überlegungen ab, die Sie in Ihrer Frage nicht erwähnt haben. Ich werde eine sehr kurze Übersicht der Optionen zur Verfügung stellen, um zu vermeiden, dass dies "zu breit" wird. Es liegt an Ihnen, Ihre Wahl zu treffen und die Details herauszufinden. Wenn Sie nicht weiterkommen, können Sie eine neue, spezifischere Frage stellen.

Mit Locate

Eine Lösung Locate beteiligt ist nur möglich, wenn Ihr Dataset vom selben Feld sortiert Sie suchen auf.

Offensichtlich ist Ihr Suchwert kein eindeutiger Schlüssel. Ich vermute also, dass Sie versuchen, die letzte Zeile zu finden, die mit dem Suchschlüssel in Daten übereinstimmt, die nach einem anderen eindeutigen Feld sortiert sind. (Ansonsten ist das Konzept von letzten bedeutungslos.)

Also ist es sehr wahrscheinlich, dass dies nicht für Sie geeignet ist; es sei denn, Ihre Daten werden nach einem zusammengesetzten Schlüssel Ihres Suchfeldes gefolgt von einem eindeutigen Schlüssel sortiert.

Der Ansatz ist einfach: Navigieren Sie vorwärts, bis Sie eine Zeile gefunden haben, in der der Suchwert nicht übereinstimmt, und rücken Sie dann um eine Zeile zurück.

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; 

Implementieren Sie Ihre eigene Suche

Dies ist geradlinig und wird immer funktionieren. Aber es ist ineffizient, mit O (n) Komplexität. Also nicht für große Datensätze empfohlen.

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

HINWEIS: Um das Verhalten von Locate widerzuspiegeln es ratsam wäre, diese Methode zu verbessern, den Fall zu behandeln, in denen ein Spiel überhaupt nicht zu finden ist. In diesem Fall sollte der aktive Datensatz nicht versehentlich als Nebeneffekt der Suche geändert werden.

Verwenden Filterung

Offensichtlich ist diese Lösung hängt davon ab, ob die Datenmenge Filterung an den Rest des Codes geeignet ist. Aber es ist eine ziemlich einfache Option, und abhängig von Faktoren, die über den Rahmen dieser Antwort hinausgehen, kann es leistungsfähiger als die vorherige Option sein.

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; 

Siehe Dokumentation auf der Filter Eigenschaft.

HINWEIS: Es kann ratsam sein, Vorsichtsmaßnahmen zu ergreifen gegen die Filter redundant einstellen.

Verwenden Sie eine Master-Detail-Beziehung

Diese Option enthalten ist, weil Ihre Frage Code die search stammt aus dem aktiven Datensatz eines anderen Datensatzes anzeigt. Sie verwenden ADO, diese Option steht Ihnen also zur Verfügung.

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

siehe Dokumentation auf master-detail relationships und auf ADO MasterFields.

Offload die Arbeit mit dem RDBMS

Schließlich ist es eine Überlegung wert, eine gespeicherte Prozedur unter Verwendung der Informationen, die Sie direkt aus der Datenbank benötigen. Der Vorteil ist, dass der Server verfügbare Indizes nutzen kann und das Potenzial hat, die performanteste Option bereitzustellen. Auch hier hängt vieles von den Einzelheiten Ihrer Bewerbung ab.

Eine Abfrage in den folgenden Zeilen kann die Basis Ihrer gespeicherten Prozedur bilden.

Dann rufen Sie Ihre gespeicherte Prozedur, und verwenden Sie ihr Ergebnis, um die gewünschte Zeile zu finden.

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

HINWEIS: Vergessen Sie nicht, um die gespeicherte Prozedur zu prüfen NULL Rückkehr, wenn keine Zeilen mit search existieren.


Allgemeiner Haftungsausschluss

All oben genannte Code ist extrem kurz und nur zur Veranschaulichung. In vielen Fällen ist zusätzlicher Code für eine stabile Implementierung erforderlich.
Zum Beispiel Möglicherweise müssen Sie DisableControls aktivieren und sie erneut aktivieren.

HINWEIS: Es ist sehr wichtig, mit dem oben bewusst zu sein, die tatsächlichen der Daten in Ihrer Datensätze zu bestellen. Wenn dies nicht berücksichtigt wird, kann dies zu einem falschen Verhalten führen. Auch die letzte Option kann eine schlechter als erwartete Leistung aufweisen, wenn Ihr Dataset nicht nach UniqueKey sortiert ist.

0

Wenn Ihre Tabelle ein Autoincrement Identitätsfeld hat, können Sie dies tun

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

Wert1 und Wert2 sind values.pass sie als Parameter die gewünschte oder setzen Sie sie in Befehlstext auf diese Weise nur Sie erhalten rudern wollen und keine Notwendigkeit zu Schleife

Verwandte Themen