Query - Scrolling

Unter Scrolling verstehen wir das Unterteilen von Abfragen in einzelne "Pakete".
Beispiel: Es wird eine Query-Abfrage ausgeführt, welche 25 Rows zurückliefert. Diese Query-Abfrage wird anschliessend erneut ausgeführt und die nächsten 25 Rows werden zurückgeliefert. Dieses Scrolling (auch"Redo" oder "Paging" genannt) wird so lange wiederholt, bis eine Query-Abfrage keine Datensätze mehr (NoNext) zurückgeliefert.
Verwenden Sie in folgenden Fällen Scrolling: Bei rechenintensiven Abfragen und/oder Abfragen über sehr viele Datensätze. Durch das Verwenden von Scrolling lassen sich Last-Spitzen (Systemauslastung) vermeiden und die Performance eines Systems kann optimal ausgenutzt werden.
Das Scrolling bei Query-Abfragen ist ähnlich implementiert, wie bei GetBo. Falls Sie also bei GetBo schon mal mit Scrolling gearbeitet haben, werden Sie sich schnell zurecht finden. Bitte beachten Sie folgende Punkte:
  • Die Such-Operatoren sind identisch. Jedoch werden "e" und "eif" bei Query-Abfragen nicht unterstützt.
  • Die Messages (MsgText) sind identisch. (NoBoth, NoPrev, NoNext)
  • Die Redo-Argumente sind identisch.
Die Reihenfolge kann bei Query-Abfragen viel flexibler gestaltet werden als bei GetBo.
  • "OrderBy"-Argument-Spalten werden automatisch zurückgegeben wenn das Scrolling aktiviert ist.
  • Sortierungen sind auch für berechnete (z.B. Addr.FullName) und virtuelle Attribute möglich.

Such-Operatoren

Such_Operatoren.jpg

Scrolling-Regeln

Zusätzlich zur ursprünglichen Abfrage (Request) für die erste Page, müssen für die Folge-Pages zwei Argumente angehängt werden:
  • #RedoData Ist jeweils im Resultat (Response) enthalten und kann 1:1 dem Folge-(Page)-Request angehängt werden.
  • #RedoArgs <Such-Operator>[,<Richtung:0|1>][,<Anzahl Rows>]
    Die Richtung und Anzahl Rows sind optional. Werden sie nicht angegeben, entsprechen sie der ursprünglichen Abfrage.
Die Rows müssen eindeutig identifizierbar sein! Mit anderen Worten: Damit Scrolling in jedem Fall korrekt funktioniert, muss sich jede zurückgegebene Row von allen anderen unterscheiden. Es ist Sache des Aufrufers, die dafür nötigen Spalten zu definieren!
Wir empfehlen für das Unterscheiden von Rows folgende Attribute zu verwenden: (Siehe auch: Zusätzliche ID-Spalten - Query - Grundlagen)
  • Bei BO-Views die Spalte "BoPid".
  • Bei Funktions-Views die Spalte "RowId".
Achtung
Achtung
Wenn (via "Related"-Argument) auf mehrere Objekte zugegriffen wird und es sich bei diesen Relationen nicht um 1:1-Beziehungen handelt, müssen für die referenzierten Objekte ebenfalls eindeutige Spalten hinzugefügt werden!
Hinweis
Hinweis
In F-Script sind die entsprechenden Scrolling-Funktionalitäten bereits komplett gekapselt. Wenn Query-Aufrufe in F-Script via die Befehle XQRY und XQRS ausgeführt werden, dann müssen die beiden Argumente #RedoData und #RedoArgs nicht manuell gesetzt werden. (Siehe hierzu auch XQRS - redo)
Betrachten wir die Anwendung von BoPid an einem einfachen Beispiel. Es sollen alle Verkaufspositionen von Auftragsbestätigungen ausgegeben werden, die einen bestimmten Artikel enthalten und für einen bestimmten Kunden (Kunden Nr. Dokument) erfasst wurden.
Query
Query
Main=SalDocItem
Columns=SalDoc.BoName,SalDocItem.BoName,Art.Number
Scrolling=ne
MaxRows=5
Filter=SalDocItem.ArtNo='TRIDENT' and SalDocItem.CustNo=1070 and SalDoc.SalProcLevelCd=SalProcLevel.Acknowledgement
OrderBy=SalDocItem.SalDocInternalNo
Das Resultat dieser Query-Abfrage liefert nun potentiell identische Rows. Ein Scrolling ist so nicht möglich.
SalDoc.BoName SalDocItem.BoName Art.Number SalDocItem.SalDocInternalNo
AB-X-09-2357
Trident White
TRIDENT
8950
AB-X-09-2357
Trident White
TRIDENT
8950
AB-X-09-2357
Trident White
TRIDENT
8950
AB-X-09-2357
Trident White
TRIDENT
8950
AB-X-09-2357
Trident White
TRIDENT
8950
Natürlich lassen sich Rows durch verschiedene zusätzliche Attribute eindeutig identifizieren. Die Verwendung der BoPid bietet sich an, weil sie immer eindeutig ist.
Query
Query
Main=SalDocItem
Columns=SalDoc.BoName,SalDocItem.BoName,Art.Number
Scrolling=ne
MaxRows=5
Filter=SalDocItem.ArtNo='TRIDENT' and SalDocItem.CustNo=1070 and SalDoc.SalProcLevelCd=SalProcLevel.Acknowledgement
OrderBy=SalDocItem.SalDocInternalNo
OrderBy=SalDocItem.BoPid
Das Resultat enthält nun eindeutige Rows.
SalDoc.BoName SalDocItem.BoName Art.Number SalDocItem.SalDocInternalNo SalDocItem.BoPid
AB-X-09-2357
Trident White
TRIDENT
8950
1699
AB-X-09-2357
Trident White
TRIDENT
8950
1738
AB-X-09-2357
Trident White
TRIDENT
8950
1739
AB-X-09-2357
Trident White
TRIDENT
8950
1747
AB-X-09-2357
Trident White
TRIDENT
8950
1749
Die Query-Abfrage kann nun so lange wiederholt werden, bis im MsgKey der Wert "NoNext" ausgegeben wird. Dann wurden alle Datensätze Rows ausgegeben bzw. abgearbeitet.
Wie bereits erwähnt, muss für das Scrolling in F-Script nicht viel getan werden. Es genügt, wenn auf dem entsprechenden Query-Result (XQRS) ein Redo durchgeführt wird. Beispiel: Nächste 10 Rows einer bestehenden Query-Abfrage mit ne auslesen.
«nXQRS(res.QueryAddr:redo,ne,,10)»
Hinweis
Hinweis
Analog gilt dies auch für Query-Abfragen via BOF-Script oder Drittanwendungen über COM.

Scrolling mit #RedoData und #RedoArgs (WebService-Schnittstelle)

Im Falle von Drittanwendung via WebServce-Schnittstelle, muss das Scrolling durch hinzufügen der Redo-Argumente implementiert werden. Beim Attribut #RedoData kann direkt RedoData aus dem Resultat des vorangegangenen Request übergeben werden.
Syntax:
  • #RedoData=[RedoData aus vorangehendem Request-Resultat]
  • #RedoArgs=SuchOperation,StartPosition,AnzahlBO
    Wenn StartPosition = 1 wird auf der ID der ersten Result-Row aufgesetzt.
    Wenn StartPosition = 0 oder leer, wird auf der ID der letzten Result-Row aufgesetzt.
Bezogen auf das obige Beispiel mit den Verkaufspositionen sieht ein Redo-Aufruf beispielsweise so aus:
Query
Main=SalDocItem
Columns=SalDoc.BoName,SalDocItem.BoName,Art.Number
Scrolling=ne
MaxRows=25
Filter=SalDocItem.ArtNo='TRIDENT' and SalDocItem.CustNo=1070 and SalDoc.SalProcLevelCd=SalProcLevel.Acknowledgement
OrderBy=SalDocItem.SalDocInternalNo
OrderBy=SalDocItem.BoPid
#RedoData=[RedoData aus vorangehendem Request-Resultat]
#RedoArgs=ne,,25
Sie können also bei Abfragen über die WebService-Schnittstelle auf RedoData zugreifen (Response) und direkt wieder dem Argument #RedoData zuweisen (Request).
Beispiel von RedoData in einer WebService-Response:
<RedoData>
  <Item>nep</Item>
  <Item>1</Item>
  <Item>1</Item>
  <Item>1011</Item>
</RedoData>

Setzen eines Startpunkts beim Scrolling

Oft möchte man bei Query-Abfragen mit Scrolling, auf einem bestimmten Startpunkt aufsetzen. Dieser Startpunkt kann beim OrderBy-Argument mitgegeben werden.
Beispiel: Es sollen Adressen ausgegeben werden. Sortiert werden soll nach dem Attribut Nachname (Addr.LastName). Es soll mit ne ab einem bestimmten Startpunkt gesucht werden.
Query
Query
Main=Addr
MaxRows=6
Columns=Addr.Number,Addr.LastName,Addr.FirstName
OrderBy=Addr.LastName,"Schild"
Scrolling=ne
Resultat
Addr.Number Addr.LastName Addr.FirstName
2
Schild
Martin
1055
Schild
Martin
1056
Schild
Martin
5510
Schild
Martin
105500
Schild
Martin
123456
Schild
Volker