Seite 1 von 1

SQLExpress: skip() mit Select ersetzen?

Verfasst: Mo, 11. Nov 2013 16:01
von satmax
Hallo,

ich will ja nicht einfach mit einem Select * from Auftrag alle Aufträge über die Leitung ziehen und dann skippen. Daher wäre mein Ansatz für ein dbSkip(-1):

Code: Alles auswählen

oCursor := SQLSelect():new("SELECT TOP 1 * FROM Auftrag ORDER BY AuftragNr DESC") // Findet den letzten Auftrag
oCursor:Execute()

// Dann ein skip(-1)
:oCursor:= SQLSelect():new("select count(*) FROM AUFTRAG WHERE AuftragNr < (?)")  //  zähle Aufträge davor
oCursor:Execute(oCursor:fieldGet("AuftragNr"))

nGoTo:=oCursorBack:FieldGet(1)    // Wahrscheinlich fehlt hier ein neues "SELECT * from Auftrag where row=nGoTo"  oder so ähnlich.....
oCursor:GoTo(nGoTo)
Habe ich mich da jetzt total verrannt oder sollte das so ähnlich funktionieren? Ich hätte auch in jeden Datensatz ein eindeutiges Feld ID (autoincrement)

Eigentlich will ich also nur ein skip nachbilden und dabei aber immer nur einen Record lesen.

Gruß
Markus

Re: SQLExpress: skip() mit Select ersetzen?

Verfasst: Mo, 11. Nov 2013 18:34
von georg
Hallo, Markus -


ja und nein.

Es ist immer (!) von der Implementierung des SQL-Servers UND der ODBC-Schnittstelle abhängig, wie Daten geliefert werden. In vielen Fällen ist die Angabe, dass Du einen speziellen Cursors willst (der z.B. Satz für Satz die Daten abruft) eben nur eine Empfehlung, und der Treiber sammelt fleissig alles ein.

Um den letzten Auftrag zu finden:

Code: Alles auswählen

SELECT Max(AuftragNR) FROM Auftrag
oder
SELECT * FROM Auftrag ORDER BY AuftragNr DESC LIMIT 1
Ansonsten entspricht die Satzanzahl vor dem letzten Auftrag der Anzahl Sätze in der Datei. Da in Deiner Anweisung

Code: Alles auswählen

select count(*) FROM AUFTRAG WHERE AuftragNr < (?)
die ORDER BY Clause fehlt, kann es sein, dass Deine Ergebnisse abweichen.


Versuchen wir eine andere gedankliche Annäherung. Angenommen, Du brauchst folgende Felder:

Auftragsnummer
Datum
Kundennummer
Kundenname
Status

Code: Alles auswählen

SELECT AuftragNr, AufDatum, AufKundenNr, Kundenname, Aufstatus FROM Auftrag AS T1 LEFT JOIN Kunden AS T2 ON T1.AufKundenNr = T2.Kundennummer ORDER BY AuftragNr DESC
Vorteil: Du rufst nur die Felder ab, die gebraucht werden - verringert den Traffic. Du hat in einer Anweisung direkt den Kundennamen mit drin, macht es übersichtlicher. Pack das Ganze in ein SQLDataSet(), und Du kannst viel damit machen.

Ein SELECT * würde Daten über die Leitung ziehen, die zu dem Zeitpunkt nicht benötigt werden. Willst Du nur einen bestimmten Zeitraum, grenze die SELECT-Anweisung durch ein entsprechendes WHERE ein.

Re: SQLExpress: skip() mit Select ersetzen?

Verfasst: Mo, 11. Nov 2013 18:49
von satmax
Danke für Deine Erklärungen.

Klar gebe ich nur die Felder an die ich brauche ;) , das ist hier nur der Einfachheit halber so geschrieben.

In diesem Fall stehen ich einfach auf den letzten von ein paar hunderttausend Aufträgen und will einfach manuell ein paar zurückblättern. Ich denke mit dem SQL Statement

Code: Alles auswählen

xSeek:= ::oCursor:fieldGet("AuftragNr")
::oCursor := SQLSelect():new("select top 1 AuftragNr FROM AUFTRAG WHERE AuftragNr < (?) order by AuftragNr desc")
::oCursor:Execute(xSeek)

bin ich schon nahe dran.

in der MMC liefert mir das folgende Statement bereits das richtige Ergebnis

Code: Alles auswählen

select top 1 AuftragNr FROM AUFTRAG WHERE AuftragNr < 184867 order by AuftragNr desc
nur im Programm noch nicht....

Re: SQLExpress: skip() mit Select ersetzen?

Verfasst: Mo, 11. Nov 2013 19:01
von georg
Hallo, Markus -


hier verwende ich MySQL, und die Anweisung "TOP 1" mag MySQL nicht - scheint also ein "Sonderweg" zu sein.

Ansonsten gibt es noch andere Wege. Ich schicke Dir mal eine PN, weil mir jetzt die Zeit fehlt, das hier auszuführen.

Re: SQLExpress: skip() mit Select ersetzen?

Verfasst: Fr, 15. Nov 2013 4:14
von AUGE_OHR
satmax hat geschrieben:Eigentlich will ich also nur ein skip nachbilden und dabei aber immer nur einen Record lesen.
diese Methoden sind IMHO beim DataSet() von Boris enthalten.
satmax hat geschrieben:In diesem Fall stehen ich einfach auf den letzten von ein paar hunderttausend Aufträgen und will einfach manuell ein paar zurückblättern.
das ist man von DBF so gewohnt ...
angenommen du hast ein Browse dann hast du auch nur eine begrenzte Anzahl von Zeilen für 1 Seite zu darstellen.
ich verwende mit PostgreSQL dafür einen CURSOR der mir ein aktuelles Result Set mit genau der Anzahl von Zeilen liefert.

Code: Alles auswählen

\\ Note : die PostgreSQL (!) Function row_number() gibt es erst ab der Version v9.x

   cVar1 := "BEGIN WORK;"
   cVar2 := "DECLARE MyCursor CURSOR FOR SELECT " + cField +;
               ", row_number() OVER (ORDER BY " + cOrder + ")"+;
               " FROM " + cTable + ;
               IF( EMPTY( cWhere ), "", " WHERE " + cWhere ) + ;
               " ORDER BY " + cOrder
   cVar3 := "MOVE  FORWARD " + cOffset + " IN MyCursor"
   cVar4 := "FETCH FORWARD " + cLimit  + " FROM MyCursor"
   cVar5 := "CLOSE MyCursor;"
   cVar6 := "COMMIT WORK;"
jede cVarX wird als Query per ::oPG:exec( cVarX ) abgeschickt.

innerhalb eines Result Set Object hat man gewöhnlich Methoden zum navigieren (skip,goto) die mit Tuple die Positionen bestimmen.

Re: SQLExpress: skip() mit Select ersetzen?

Verfasst: Fr, 15. Nov 2013 8:49
von brandelh
ich bin nicht so drin bei den "cursorn" und was der jeweilige ODBC Treiber kann, daher habe ich es bei mir so gelöst, dass ich mit SELECT ID,name FROM xyz WHERE ... (readonly forward cursor kostet am wenigsten) genau die Datensätze mit primary Key und Text für die Anzeige (Baum, Browser etc.) hole und in ein Array umschaufle die ich jetzt brauche ! Nun Skippe ich im Array und fordere jeden einzelnen Satz dann an, wenn ich seine Daten benötige. Geänderte Daten sende ich per UPDATE ... WHERE ID = sID (Syntax aus dem Kopf, kann Fehler enthalten ;-) ...

Re: SQLExpress: skip() mit Select ersetzen?

Verfasst: Fr, 15. Nov 2013 10:27
von satmax
Mein Ansatz geht jetzt in die Richtung, bei Select auf keinen Fall Select * zu benutzen. Ich mache 2 Cursor, einen

Code: Alles auswählen

Pseudocode:
oCursorSkip := SELECT auftragnummer FROM auftrag
mit dem kann ich auch problemlos arbeiten wenn mehr all 300000 Aufträge in der DB sind und kann alle Funktionen benutzen (skip, reccount,...)

Dann einen zweiten Cursor

Code: Alles auswählen

Pseudocode:
oCursor := SELECT VieleFelder from Auftrag where auftragsnummer == oCursorSkip
der beinhaltet alle Daten und wird bei jedem skip neu eingelesen und die Daten angezeigt bzw. zum Bearbeiten bereit gestellt. Das ganze ist sehr einfach und effizient.

Gruß
Markus