Entwickler-Ecke
Datenbanken - Gibt es Befehle: SELECT FIRST und SELECT NEXT usw.
JRegier - Fr 19.08.05 07:11
Titel: Gibt es Befehle: SELECT FIRST und SELECT NEXT usw.
Hi, wie ich gelesen habe wird davon abgeraten bei eine Client-Server-Modell einfach
SELECT * FROM `tabelle` auszuführen! Sondern die Transactionmenge so gering wie möglich
zu halten, vorzugsweise nur ein Datensatz!
Ich habe keine Ahnung wie solch ein Befehl in SQL aussehen könnte, also ich möchte dass z.B.
beim Start der Erste Datensatz abgefrufen wird und beim Befehl Fisrt/Next/Prior/Last immer
jeweils der richtige Datensatz selektiert wird! OK ich könnte einfach:
SELECT * FROM `tabelle` WHERE ID = :X
ausführen! Aber wer sagt mir das diese ID überhaupt noch vorhanden ist wenn die nicht schon
bereits gelöscht wurde! (Ich meine hier mit ID ein AutoInc Feld) aber sagt mal wie ist es
wenn eine Tabelle kein AutoInc Feld hat?
Ich müßte also ein Next/Prior.. an der Physikalischen Tabelle ausführen also in der Art
SELECT FIRST, SELECT PRIOR, SELECT NEXT, SELECT LAST aber die Befehlkombination gibts
wohl nicht oder?
noidic - Fr 19.08.05 08:26
Hi!
Nein, solche Befehle gibt es zumindest bei den mir bekannten Datenbanken nicht. Ist auch eigentlich nciht nötig, denn normalerweise bieten die Zugriffskomponenten wie TQuery u.ä. die gewünschte Funktionalität bereits mit ( nennt sich dann FetchAll oder sowas in der Art, mal die OH befragen ).
Ansonsten macht es Sinn, um die Datenmenge zu begrenzen, nicht select * aufzurufen, sondern die Spalten einzeln zu selektieren ( ausser man braucht wirklich alle ). Das hat außerdem den Vorteil, das nach einer Änderung der Tabelle Code-Stellen leichter gefunden werden, die noch das alte Format erwarten ( es schlägt direkt die Abfrage fehl, nicht irgendwas später ).
davidbaumann - Fr 19.08.05 09:03
SELECT * FROM `tabelle` WHERE ID >= X order by X limit 1
noidic - Fr 19.08.05 09:22
Limit gibts nicht bei allen Datenbanken ( ich kenne ausser MySQL keine, dies kann ), ausserdem kriegst du damit zwar wunderbar nur einen Datensatz, aber auch immer den selben.
JRegier - Fr 19.08.05 09:23
noidic hat folgendes geschrieben: |
Hi!
Nein, solche Befehle gibt es zumindest bei den mir bekannten Datenbanken nicht. Ist auch eigentlich nciht nötig, denn normalerweise bieten die Zugriffskomponenten wie TQuery u.ä. die gewünschte Funktionalität bereits mit ( nennt sich dann FetchAll oder sowas in der Art, mal die OH befragen ).
Ansonsten macht es Sinn, um die Datenmenge zu begrenzen, nicht select * aufzurufen, sondern die Spalten einzeln zu selektieren ( ausser man braucht wirklich alle ). Das hat außerdem den Vorteil, das nach einer Änderung der Tabelle Code-Stellen leichter gefunden werden, die noch das alte Format erwarten ( es schlägt direkt die Abfrage fehl, nicht irgendwas später ). |
Vieleicht hast mich falsch verstanden?
Vorerst mal möchte ich, das mit den Spalten, ein Sachverhalt erläutern:
-----------------
Nehmen wir mal an ich habe eine INNER JOIN Abfrage und kann nicht die Datenmenge editieren,
nun verwenden ich eine andere Query in der ich den UPDATE Statement reinschreibe!
z.B ich habe eine Tabelle:
PERSON
-------------------------------
ID* | NAME | VORNAME | STRASSE | PLZ | ORT
Am besten ich selektiere bei der INNER JOIN Abfrage mit
Delphi-Quelltext
1:
| SelectQuery.SQL.Text := 'SELECT * FROM `PERSON` A INNER JOIN `FIRMA` B ON A.`ID` = B.`PERSON_ID` WHERE B.`ID` = 12'; |
Weil ich hier mit * Selektiert habe kann ich den Datensatz auch dann identifizieren auch wenn
es keinen Primary Key gibt!
Also ich schreibe einfach in die UpdateQuery rein:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| with UpdateQuery do begin SQL.Text := 'UPDATE PERSON SET NAME = :NAME, VORNAME = :VORNAME, STRASSE = :STRASSE, '+ 'PLZ = :PLZ, ORT = :ORT '+ 'WHERE ID = :OLD_ID AND NAME = :OLD_NAME AND VORNAME = :OLD_VORNAME AND '+ 'STRASSE = :OLD_STRASSE AND PLZ = :OLD_PLZ AND ORT = :OLD_ORT';
ParamByName('NAME').AsString := NewName; ... ... ParamByName('OLD_ID).AsInteger := SelectQuery.FieldByName('ID').AsInteger; ParamByName('OLD_NAME).AsInteger := SelectQuery.FieldByName('Name').AsString; ... |
Wenn ich alle Felder angebe kann also immer ein Datensatz identifiziert werden! Oder auch nicht?
Wenn es mehrere gleiche Datensätze gibt werden die ja alle hiermit aktualisiert!
Gibt es einen Weg bei mehreren Gleichen Datensätzen das nur einer geupdatet wird?
ABER WAS ICH MIT DIESEM THREAD HIER SAGEN WOLLTE:
Wenn es um Cleint Server Modell geht, wird davon abgeraten alle Datensätze
mit : SELECT * FROM `tabelle`
ohne WHERE zu selektieren also
vorzüglich nur ein Datensatz! Darum die Frage nach SELECT FIRST, SELECT NEXT usw.
noidic - Fr 19.08.05 09:33
Du hast recht, habe dich falsch verstanden :) Ich dachte, es ginge dir darum, möglichst wenige Datensätze in einem Schwung vom Server zu ziehen ( warum auch immer ).
Nun verstehe ich dein Problem nicht mehr...
Ob du mit Select * selektierst oder die Spalten konkret aufführst hat keinen Einfluss darauf, dass du einen Datensatz identifizieren kannst, denn dafür ist ja der Primärschlüssel da ( in deinem Fall das Feld ID nehme ich an ). Also nimmst du die entpsrechende Spalte einfach mit auf.
Zu der Frage nach dem Update: Wenn mehrere Datensätze die Bedingung erfüllen, werden auch alle geändert. Punkt.
Und zum letzten Punkt:
Selects ohne Bedingung sollte man nach Möglichkeit vermeiden. Zumeist ist nur eine Teilmenge der Daten relevant, und die sollte man dann schon beim Select eingrenzen. Dies geht nur mit geschickt formulierten Where-Klauseln.
JRegier - Fr 19.08.05 09:54
noidic hat folgendes geschrieben: |
Du hast recht, habe dich falsch verstanden :) Ich dachte, es ginge dir darum, möglichst wenige Datensätze in einem Schwung vom Server zu ziehen ( warum auch immer ).
Nun verstehe ich dein Problem nicht mehr...
|
Nein dann hast du es doch verstanden, wenn du meinst möglichst wenige Datensätze in einem Schwung zu selektieren, nur weil du was von
Spalten geschrieben hast darum dieser umfangreiche Beitrag!
noidic hat folgendes geschrieben: |
Ob du mit Select * selektierst oder die Spalten konkret aufführst hat keinen Einfluss darauf, dass du einen Datensatz identifizieren kannst, denn dafür ist ja der Primärschlüssel da ( in deinem Fall das Feld ID nehme ich an ). Also nimmst du die entpsrechende Spalte einfach mit auf.
|
Aber haben den die Tabellen immer einen Primärschlüssel?
noidic hat folgendes geschrieben: |
Zu der Frage nach dem Update: Wenn mehrere Datensätze die Bedingung erfüllen, werden auch alle geändert. Punkt.
|
Na ja habe ich mir auch gedacht, aber vorher wollte ich mit Select Edit und dann Post der Query ausführen dann müßte eigentlich
nur ein Datensatz geupdatet werden! Aber das mit Query.Post funzte nicht, ich benutze z.Z. Zeos ZQuery und greife auf eine MySQL
Datenbank zu!
noidic hat folgendes geschrieben: |
Und zum letzten Punkt:
Selects ohne Bedingung sollte man nach Möglichkeit vermeiden. Zumeist ist nur eine Teilmenge der Daten relevant, und die sollte man dann schon beim Select eingrenzen. Dies geht nur mit geschickt formulierten Where-Klauseln. |
[/quote]
OK, Selects ohne Bedingungen verstehe ich, bei Master-Detail-Verknüfungen sind bei den Detail-Tabellen sowiese nur Teildaten Selektiert
aber in der Haupttabelle/Mastertabelle die von keiner Abhängig ist sind ja alle Datensätze selektiert also wollte ich da sowas realisieren
dass beim Navigieren jeweils nur ein Datensatz selektiert ist also quasi SELECT FIRST beim Transactionstart und dann beim Navigieren
SELECT NEXT .. etc.
Wie könnte denn die Where Clausel aussehen? Irgendjemand eine Idee?
noidic - Fr 19.08.05 10:19
Hi!
Ich kenn die Komponenten nicht, die du verwendest, aber schau dir meine erste Antwort bezüglich den Möglichkeiten des TQuery nochmal an. Da müsste es eigentlich eine Möglichkeit geben, der Komponente zu sagen, sie soll die Datensätze nach Bedarf ziehen.
Zum Thema Primärschlüssel:
Jede aktive Tabelle ( also alles ausser History-Tabellen ) sollte einen Primärschlüssel haben, alles andere ist imo schlechtes DB-Design da:
1. Keine Eindeutige Datensatz-Identifizierung möglich ist ( wenn ich dafür nen unique index baue, kann ich daraus direkt nen pk machen ).
2. Joins mit dieser Tabelle elend langsam werden, da immer ein full table scan gemacht wird
JRegier - Fr 19.08.05 11:10
noidic hat folgendes geschrieben: |
Hi!
Ich kenn die Komponenten nicht, die du verwendest, aber schau dir meine erste Antwort bezüglich den Möglichkeiten des TQuery nochmal an. Da müsste es eigentlich eine Möglichkeit geben, der Komponente zu sagen, sie soll die Datensätze nach Bedarf ziehen.
|
Ja ich habe mir FetchAll: in der Delphi Hilfe angesehen!
Da steht:
begin
Mit FetchAll können Sie die Belastung des Netzwerks verringern, wenn die Zwischenspeicherung von Aktualisierungen aktiv ist. FetchAll ruft CheckBrowseMode auf, um alle Änderungen einzutragen. Anschließend werden alle Datensätze von der aktuellen Cursorposition bis zum Dateiende abgerufen und lokal gespeichert.
Hinweis
Die Verwendung von FetchAll ist nicht immer sinnvoll. Wird beispielsweise in einer Anwendung auf eine Datenbank zugegriffen, die von mehreren Clients gleichzeitig verwendet wird, und werden häufig Datensätze von mehreren Clients aktualisiert, sollten nicht alle Datensätze gleichzeitig abgerufen werden, da einige dieser Datensätze möglicherweise in anderen Anwendungen geändert wurden. Sie müssen also die Vorteile einer geringeren Netzwerkbelastung gegen die Nachteile abwägen, die aus Konflikten in den Datensätzen entstehen.
end;
Also alle Datensätze werden abgerufen und lokal gespeichert! Also doch nicht das richtige!
noidic - Fr 19.08.05 11:18
Eben genau das solltest du ja dann abschalten :)
JRegier - Fr 19.08.05 14:12
noidic hat folgendes geschrieben: |
| Eben genau das solltest du ja dann abschalten :) |
FetchAll ist eine procedure! Nicht eine Eigenschaft! Oder einfach
not FetchAll aufrufen? :D
hansa - Fr 19.08.05 14:46
Hi,
Du mußt etwas mehr Systematik in das Programm reinbringen. Der * hat mit Fetchall usw. nur bedingt etwas zu tun. Warum steht das Update bei dir im Source ? Dafür sind normalerweise die Zugriffskomponenten zuständig (insbesondere TDataSet und Nachfolger). Da wird der Kram hinterlegt (auch für insert, delete usw.). Im Programm benutzt Du dann nur noch Dataset.Edit um zu ändern und dann mit Dataset.Post speichern. Alternativ kann man (so mache ich es) Stored Procedures zum speichern benutzen. MySql kann das (zumindest noch) nicht.
Der * spielt bei Select allerdings schon eine große Rolle.
Beispiel : Brauche Kunden-Tel.Nr. Liste.
SELECT * FROM KUNDE liefert mir jetzt auch Skonto, Lieferadresse usw. vielleicht auch Firlefanz wie Geburtstag. Also unwichtiges Zeug für meine Liste. Die bräuchte nur SELECT ID,NR,NAME,ORT,TELNR FROM KUNDE
Je nach Anzahl der Dataset-Felder oder der Größe des Ganzen macht sich der Unterschied sogar bei einem Einzelplatz-System richtig bemerkbar.
Jetzt zu Deinem SELECT NEXT. Im Programm mußt Du mit Dataset.First, next und DataSet.EOF hantieren. Dies bedeutet, daß eine per WHERE möglichst eingeschränkte Ergebnismenge von der Datenbank zur Verfügung steht. Sofern auch auf den * verzichtet wird, dann geht das auch Ratzfatz.
JRegier - Fr 19.08.05 15:19
hansa hat folgendes geschrieben: |
Hi,
Du mußt etwas mehr Systematik in das Programm reinbringen. Der * hat mit Fetchall usw. nur bedingt etwas zu tun. Warum steht das Update bei dir im Source ? Dafür sind normalerweise die Zugriffskomponenten zuständig (insbesondere TDataSet und Nachfolger). Da wird der Kram hinterlegt (auch für insert, delete usw.). Im Programm benutzt Du dann nur noch Dataset.Edit um zu ändern und dann mit Dataset.Post speichern. Alternativ kann man (so mache ich es) Stored Procedures zum speichern benutzen. MySql kann das (zumindest noch) nicht.
Der * spielt bei Select allerdings schon eine große Rolle.
Beispiel : Brauche Kunden-Tel.Nr. Liste.
SELECT * FROM KUNDE liefert mir jetzt auch Skonto, Lieferadresse usw. vielleicht auch Firlefanz wie Geburtstag. Also unwichtiges Zeug für meine Liste. Die bräuchte nur SELECT ID,NR,NAME,ORT,TELNR FROM KUNDE
Je nach Anzahl der Dataset-Felder oder der Größe des Ganzen macht sich der Unterschied sogar bei einem Einzelplatz-System richtig bemerkbar.
Jetzt zu Deinem SELECT NEXT. Im Programm mußt Du mit Dataset.First, next und DataSet.EOF hantieren. Dies bedeutet, daß eine per WHERE möglichst eingeschränkte Ergebnismenge von der Datenbank zur Verfügung steht. Sofern auch auf den * verzichtet wird, dann geht das auch Ratzfatz. |
Also nochmal, ich schreibe ein Programm mit dem man sich eine DB Anwendungs - Oberfläche zusammenbaut, d.h.
ich verwende schonmal Zeos mit denen ich schon einigermaßen Universal bin um auf verschiedenste DB's zugreifen
zu können! Nun muß mein Programm die Statements zur Laufzeit beim Start erstellen, so!
Also ich habe z.B. eine N:1 Verknüpfung, so und da ist z.B. die "Slave" Tabelle mit dieser N_ID verknüpft
und es gibt auch Tabellen bei denen da Kein AutoInc Feld nicht sinnvoll ist, und wenn kein AutoInc Feld
vorhanden ist dann kann ich den Datensatz ja nur über Werte aller Felder identifizieren von daher
habe ich auch gemeint mit * zu selektieren um nur den Datensatz immer identifizieren zu können!
:idea: :idea: :idea:
Aber vieleicht sollte ich eifach als Voraussetzung für mein Programm dem Anwender mitteilen dass er in jeder
Tabelle ein AutoInc Feld anlegt das würde die sache erhenblich erleichtern!
Aber nun zum Problem, Teilselektion!
Also wie hier in diesem Topic schon erwähnt wurde:
First) SELECT * FROM `tabelle` WHERE ID = SELECT MIN(ID) FROM `tabelle` LIMIT 1';
Next ) SELECT * FROM `tabelle` WHERE ID > LASTID LIMIT 1';
Prior) SELECT * FROM `tabelle` WHERE ID < LASTID LIMIT 1';
Last ) SELECT * FROM `tabelle` WHERE ID = SELECT MAX(ID) FROM `tabelle`';
Aber was ist wenn ich nach einem anderen Feld sortiere?
First) SELECT * FROM `tabelle` WHERE '+Sortierfeld+' = ' SELECT MIN('+Sortierfeld+') FROM `tabelle` LIMIT 1';
Next ) SELECT * FROM `tabelle' WHERE '+Sortierfeld+' > LastValue LIMIT 1';
...
So könnte es klappen oder?
noidic - Fr 19.08.05 15:20
Also ich schreibe updates und inserts ausschließlich als SQL-Statements selbst. Liegt zum grössten Teil daran, dass ich selten Statements ohne Joins habe und ich es einfach übersichtlicher finde. Allein wenn ich das Problem habe, dass irgendwas innerhalb einer Software was in ne Tabelle schreibt und ich rausfinden muss, was.
JRegier - Fr 19.08.05 15:29
noidic hat folgendes geschrieben: |
| Also ich schreibe updates und inserts ausschließlich als SQL-Statements selbst. Liegt zum grössten Teil daran, dass ich selten Statements ohne Joins habe und ich es einfach übersichtlicher finde. Allein wenn ich das Problem habe, dass irgendwas innerhalb einer Software was in ne Tabelle schreibt und ich rausfinden muss, was. |
Updates und Insert muß mein Programm aber in diesem Fall selbst erstellen, siehe mein letzter Beitrag, um welche Art Software
es sich handelt an der ich zur Zeit bastle!
Ah jetzt Fällts mir ein: Wie ich auch beim letzten Beitrag erwähnt habe wenn ich anders sortiere also nicht nach ID
dann wenn es nach mehreren Feldern Sortiert wird kann ich die Art Selection doch nicht machen, es wird nicht einfach
wenn ich da Sorierungen noch mit ASC und DESC gemischt habe! Oder, ich denke mal nach dem Ersten Feld nach dem Sortiert
wird werden alle Teildatensätze einfach Selektiert und demenstprechend die Anderen Sortiert und wenn ich EOF bekomme
kommen die nächsten Teildatensätze!
noidic - Fr 19.08.05 15:36
Mein Hinweis bezog sich auf die Idee mit Dataset.Edit und .Post, also ich mache das halt auch so, wie du.
Ich glaube bei dir gibts noch eine Verwirrung mit AutoInc und Primärschlüssel.
Auch Tabellen ohne AutoInc-Feld können einen Primärschlüssel haben, evtl. auch über mehrere Felder hinweg, das ist nicht das selbe. Und über den Primärschlüssel identifizierst du die Datensätze, dazu brauchst du nicht alle Werte.
Wenn du nun Tabellen hast, wo kein Primärschlüssel ist, musst du dich auf die DB-spezifischen Möglichkeiten zur Datensatzidentifkikation verlassen ( bei Oracle z.B. die RowID ).
JRegier - Fr 19.08.05 15:41
noidic hat folgendes geschrieben: |
Mein Hinweis bezog sich auf die Idee mit Dataset.Edit und .Post, also ich mache das halt auch so, wie du.
Ich glaube bei dir gibts noch eine Verwirrung mit AutoInc und Primärschlüssel.
Auch Tabellen ohne AutoInc-Feld können einen Primärschlüssel haben, evtl. auch über mehrere Felder hinweg, das ist nicht das selbe. Und über den Primärschlüssel identifizierst du die Datensätze, dazu brauchst du nicht alle Werte.
Wenn du nun Tabellen hast, wo kein Primärschlüssel ist, musst du dich auf die DB-spezifischen Möglichkeiten zur Datensatzidentifkikation verlassen ( bei Oracle z.B. die RowID ). |
Ah kann sein, bei einem AutoInc Feld wird immer dafür gesorgt das der immer unterschiedlich ist von Datensatz zu Datensatz weil der ja
zählt! Und wer sorgt bei eine Primary Key dafür dass der bei jedem Datensatz unteschiedlich ist?
noidic - Fr 19.08.05 16:16
Die Datenbank. Wenn du versuchst, einen Datensatz einzufügen bzw. so zu ändern, das ein PK doppelt vorhanden wäre, schmeisst die Datenbank nen Fehler.
hansa - Fr 19.08.05 18:44
JRegier hat folgendes geschrieben: |
| ...Und wer sorgt bei eine Primary Key dafür dass der bei jedem Datensatz unteschiedlich ist? |
Verwende dafür immer eine ID. Der Rest muß dann über UNIQUE (notfalls zusammengesetzte) und FOREIGN Keys gemacht werden. Ein Trigger vergibt die ID. Ein Generator enthält den Wert, der vom Trigger hochgezählt wird. Den Rest kann ich mir aber sparen. Trigger gehen bei MySql ja auch nicht. :autsch: Es gibt jetzt 2 Möglichkeiten : anständige DB verwenden oder neue MySql-Beta Version.
JRegier - Fr 19.08.05 20:58
hansa hat folgendes geschrieben: |
JRegier hat folgendes geschrieben: | | ...Und wer sorgt bei eine Primary Key dafür dass der bei jedem Datensatz unteschiedlich ist? |
Verwende dafür immer eine ID. Der Rest muß dann über UNIQUE (notfalls zusammengesetzte) und FOREIGN Keys gemacht werden. Ein Trigger vergibt die ID. Ein Generator enthält den Wert, der vom Trigger hochgezählt wird. Den Rest kann ich mir aber sparen. Trigger gehen bei MySql ja auch nicht. :autsch: Es gibt jetzt 2 Möglichkeiten : anständige DB verwenden oder neue MySql-Beta Version. |
Ja wofür den Trigger wenn ich da AutoInc Feld habe?
alzaimar - Fr 19.08.05 21:06
1. Benutz doch Cursors, jede richtige DB hat sowas.
2. Wenn Deine DB sowas wie LIMIT / TOP oder so beherrscht, also das bei einem SELECT nur maximal N Zeilen geliefert werden, dann kannst Du dir die Daten paketweise holen. Dazu erzeugst Du am besten einen Primary Key auf das ID-Feld und dann:
Du rufst die Daten paketweise ab, und zwar so:
"select * from tabelle where ID>:x Limit 100" oder bei MSSQL
"select top 100 * from tabelle where ID>:x"
beim 1.Aufruf ist 'x' = 0, also bekommst du die obersten 100 Zeilen. Nun kannst Du im Client damit hin und her laufen. Unten angekommen, nimmst Du die ID der letzten Zeile deine Paketes (nenn sie Y) und rufe das nächste Paket ab:
"select top 100 * from tabelle where ID>Y"
Du bekommst automatisch das nächste Paket. So kannst Du sehr einfach vorwärts scrollen,. Mit ein wenig Gehirnschmalz kannst das auch Rückwärts.
hansa - Fr 19.08.05 21:57
Gibts in den 4er Versionen schon Trigger ? Von einem Standard-SQL AutoInc Feld habe ich auch noch nichts gehört. Poste bitte mal davon einen Source-Schnipsel. Ein Trigger ist jedenfalls sowieso besser. Ich lasse den ja nicht nur die ID vergeben, sondern z.B. auch das Anlegedatum u.a. ! Mit sowas kann man schön die DAU-Dummheiten zurückverfolgen. :mrgreen: Natürlich gibt es auch einen Update-Trigger, der öhnliche Aufgaben zu erfüllen hat. 8)
JRegier - Fr 19.08.05 22:06
alzaimar hat folgendes geschrieben: |
1. Benutz doch Cursors, jede richtige DB hat sowas.
2. Wenn Deine DB sowas wie LIMIT / TOP oder so beherrscht, also das bei einem SELECT nur maximal N Zeilen geliefert werden, dann kannst Du dir die Daten paketweise holen. Dazu erzeugst Du am besten einen Primary Key auf das ID-Feld und dann:
Du rufst die Daten paketweise ab, und zwar so:
"select * from tabelle where ID>:x Limit 100" oder bei MSSQL
"select top 100 * from tabelle where ID>:x"
beim 1.Aufruf ist 'x' = 0, also bekommst du die obersten 100 Zeilen. Nun kannst Du im Client damit hin und her laufen. Unten angekommen, nimmst Du die ID der letzten Zeile deine Paketes (nenn sie Y) und rufe das nächste Paket ab:
"select top 100 * from tabelle where ID>Y"
Du bekommst automatisch das nächste Paket. So kannst Du sehr einfach vorwärts scrollen,. Mit ein wenig Gehirnschmalz kannst das auch Rückwärts. |
Ja meine ich doch wie ich ein paar Beiträge zurück schon ansatzweise dasselbe erklärt habe wie du hier!
Aber wie ich auch noch erwähnt habe wenn ich nicht nach der ID sortiere sondern nach andern Feldern
dann müßte es noch etwas anders aussehen!
Nehmen wir an meine Sortieranweisung sieht folgendermaßen aus:
ORDER BY NAME ASC, VORNAME DESC, STRASSE ASC, HNR DESC
dann verwende ich anstatt das ID Feld das Feld NAME
und übernehme die anderen Sortieranweisungen wie sie sind
Also so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| Query.SQL.Text := 'SELECT * FROM `person` WHERE NAME = (SELECT MIN(NAME) FROM `person`) ORDER BY VORNAME DESC, STRASSE ASC, HNR DESC'; Query.Open; LAST_RESULT_VALUE := Query.FieldByName('NAME').Value; Query.SQL.Text := 'SELECT * FROM `person` WHERE NAME > :LAST_RESULT_VALUE LIMIT 1'; Query.ParamByName('LAST_RESULT_VALUE').Value := LAST_RESULT_VALUE; Query.Open; LAST_RESULT_TEMP_VALUE := Query.FieldByName('NAME').Value; Query.SQL.Text := 'SELECT COUNT(*) AS ANZAHL FROM `person` WHERE NAME = :LAST_RESULT_TEMP_VALUE'; Query.ParamByName('LAST_RESULT_VALUE').Value := LAST_RESULT_TEMP_VALUE; Query.Open; ANZAHL := Query.FieldByName('ANZAHL').AsInteger;
Query.SQL.Text := 'SELECT * FROM `person` WHERE NAME > :LAST_RESULT_VALUE ORDER BY VORNAME DESC, STRASSE ASC, HNR DESC LIMIT :ANZAHL'; Query.ParamByName('LAST_RESULT_VALUE').Value := LAST_RESULT_VALUE; Query.ParamByName('ANZAHL').AsInteger := ANZAHL; Query.Open;
|
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!