Anmelden

View Full Version : Datensätze blockweise auslesen



Easyrider
12-12-06, 15:18
Hallo,

ich sitze grad hier und schaue wie ich es auf die Reihe bekomme Datensätze blockweise auszulesen. Dabei hab ich folgende Möglichkeiten bis jetzt gefunden:

a) FETCH X ROWS ONLY

Der Befehl gibt mir schonmal X Zeilen zurück. Aber sowas wie ein NEXT X gibts nicht, wenn meine Recherchen stimmen. Hab ich da irgendwo etwas übersehen? Gibt es doch so einen Befehl?

b) Eine dynamische Spaltennummerierung zur Laufzeit

Mit diesem kleinen "Trick" kann man schon blockweise auslesen, blos hat die Sache einen großen Nachteil: Versuche ich 200.000+ Datensätze zu lesen, dauert das teilweise extrem lange. Die CPU des Servers läuft auf 100%, andere Datenbankabfragen sind während der Zeit unmöglich. Somit ist diese Lösung nicht wirklich das gelbe vom Ei...

c) eine fixe Spaltennummerierung in der Tabelle

Ok, Blockweise auslesen möglich. Aber wie handlet man dann ein Delete mittendrin? Alle höheren Zeilennummer aktualisieren? Bei X-Hunderttausend Datensätzen wieder ein Performance-Problem. Nicht aktualisieren ist auch keine Option.


So, nun hoffe ich das ein paar von euch einen Vorschlag haben. Meine Ideen sind langsam zu Ende :(

mfg

Easy

Fuerchau
12-12-06, 15:31
FETCH X ROWS liest max. soviele Sätze, wie in X angegeben. Die Struktur muss allerdings mindestens genausoviele Vorkommen aufweisen, wie du benötigst.
In der SQLCA steht dann auch, wieviele Zeilen tatsächlich gelesen wurden (kann ja ggf. auch weniger sein).

Einen positionierten Update (update current cursor) oder Delete kannst du allerdings vergessen, da es keinen Current-Record gibt.
Also eine geblockte Verarbeitung schließt einen Update-Cursor aus.

Delete oder Update solltest du dann sowieso als eigene SQL-Anweisung mit Key (also Where-Klausel) kodieren.

hww
12-12-06, 16:42
Hallo Easy,

ich vermute, Du willst immer X Records am Bildschirm anzeigen, und dynamisch nachladen.

Falls dies so ist, halte den Cursor offen und lasse einen Counter laufen, mit dem Du X Sätze liest.

Falls Du zwischenzeitlich gelöschte, oder aktualisierte Datensätze mitbekommen musst, lies den Block erneut - hierzu musst Du den Key merken.

Gruß

Easyrider
12-12-06, 16:48
FETCH X ROWS liest max. soviele Sätze, wie in X angegeben.

Jo, soweit war ich auch schon.


Die Struktur muss allerdings mindestens genausoviele Vorkommen aufweisen, wie du benötigst.

Danke, wieder was neues gelernt :)


In der SQLCA steht dann auch, wieviele Zeilen tatsächlich gelesen wurden (kann ja ggf. auch weniger sein).

Also das ist mir nun neu... "SQL Communication Area" spuckt mir Google da aus. Mich interessiert aber weniger wieviele Zeilen er genau gelesen hat, sondern wie ich ihm sage das ich nur so und so viele Zeilen will.


Einen positionierten Update (update current cursor) oder Delete kannst du allerdings vergessen, da es keinen Current-Record gibt.
Also eine geblockte Verarbeitung schließt einen Update-Cursor aus.

Cursor sollten in dieser Anwendung nicht benutzt werden (Vorgabe des Projektleiters).


Delete oder Update solltest du dann sowieso als eigene SQL-Anweisung mit Key (also Where-Klausel) kodieren.

Klar, Where´s sind natürlich dabei. Die Vorschläge oben waren rein theoretischer Natur, keine direkten SQL-Commands ;)


Hallo Easy,

ich vermute, Du willst immer X Records am Bildschirm anzeigen, und dynamisch nachladen.

Falls dies so ist, halte den Cursor offen und lasse einen Counter laufen, mit dem Du X Sätze liest.

Falls Du zwischenzeitlich gelöschte, oder aktualisierte Datensätze mitbekommen musst, lies den Block erneut - hierzu musst Du den Key merken.

Gruß

Hallo hww,

geht das ganze auch ohne Cursor? Laut Aussage meines Projektleiters soll ich keine Cursor benutzen, wenn möglich.


Ich erklärs nochmal genauer was ich brauche:

Button-Klick1: Die ersten 1000 Datensätze von 12.000 werden ausgelesen und angezeigt.
Button-Klick2: Die nächsten 1000 Datensätze (also die Range von 1000-2000) von 12.000 werden ausgelesen und angezeigt, etc etc...

Hoffe das war Verständlich.

mfg

Easy

P.S.: Vielen Dank für die schnellen Antworten

Fuerchau
12-12-06, 19:03
Das "wenn möglich" gibt dir ja Gelegenheit.
Also: Ohne Cursor funktioniert ein Select nur, wenn max. genau 1 Zeile erwartet wird.
In diesem Fall kodiert man einen "select ... into ...".

Alle anderen Select's gehen nur mit Cursor (ohne Cursor kein Fetch).
Die SQLCA musst du auf jeden Fall auswerten:
SQLCOD = 100 => keine Daten.
Allerdings liefert der letzte Fetch ebenfalls SQLCOD=100, nur in der Struktur können trotzdem Sätze gelesen worden sein (Z.B. nur 11999 Sätze).
Dann musst du eben noch 999 Sätze verarbeiten, deine Struktur ist eben nicht vollständig gefüllt.
Die nachfolgenden Vorkommen der Mehrfachstruktur habe immer noch den VORHERIGEN Inhalt !!!

Und wenn wir über RPGLE sprechen kann der Fetch dir den Speicher zerhauen, wenn deine Struktur weniger Vorkommen hat, als du im Fetch angibst.

hww
13-12-06, 06:55
Jo, soweit war ich auch schon.



Danke, wieder was neues gelernt :)



Also das ist mir nun neu... "SQL Communication Area" spuckt mir Google da aus. Mich interessiert aber weniger wieviele Zeilen er genau gelesen hat, sondern wie ich ihm sage das ich nur so und so viele Zeilen will.



Cursor sollten in dieser Anwendung nicht benutzt werden (Vorgabe des Projektleiters).



Klar, Where´s sind natürlich dabei. Die Vorschläge oben waren rein theoretischer Natur, keine direkten SQL-Commands ;)



Hallo hww,

geht das ganze auch ohne Cursor? Laut Aussage meines Projektleiters soll ich keine Cursor benutzen, wenn möglich.


Ich erklärs nochmal genauer was ich brauche:

Button-Klick1: Die ersten 1000 Datensätze von 12.000 werden ausgelesen und angezeigt.
Button-Klick2: Die nächsten 1000 Datensätze (also die Range von 1000-2000) von 12.000 werden ausgelesen und angezeigt, etc etc...

Hoffe das war Verständlich.

mfg

Easy

P.S.: Vielen Dank für die schnellen Antworten

ohne Cursor kannst Du das haken!

Gruß

Easyrider
13-12-06, 07:53
Alle anderen Select's gehen nur mit Cursor (ohne Cursor kein Fetch).
Die SQLCA musst du auf jeden Fall auswerten:
SQLCOD = 100 => keine Daten.
Allerdings liefert der letzte Fetch ebenfalls SQLCOD=100, nur in der Struktur können trotzdem Sätze gelesen worden sein (Z.B. nur 11999 Sätze).
Dann musst du eben noch 999 Sätze verarbeiten, deine Struktur ist eben nicht vollständig gefüllt.
Die nachfolgenden Vorkommen der Mehrfachstruktur habe immer noch den VORHERIGEN Inhalt !!!

Und wenn wir über RPGLE sprechen kann der Fetch dir den Speicher zerhauen, wenn deine Struktur weniger Vorkommen hat, als du im Fetch angibst.

Ok, nun weiß ich wie das Zeug auf der AS400 geht. Aber ich entwickle in .NET über die IBM-Schnittstelle, wie bekomm ich den nun die Objekte da raus? ^^ Alles muss immer so schwer sein :p

Achja, sorry für das dumme Nachgefrage, bin nunmal ein Anfänger...

Fuerchau
13-12-06, 08:38
Nun, da bist du ggf. hier falsch.
Aber in soweit:

.NET arbeitet immer asynchron !
Wieviele Sätze blockweise verarbeitet werden bestimmst du über die PageSize (o.ä.).
.NET regelt den Cursor intern !

Es funktionieren auch Update und Delete, allerdings BATCH.
Für die AS/400-Dateien muss nur ein UNIQUE-Key vorhanden sein, dann kann .NET den Update/Delete automatisch als SQL definieren, ansonsten wird diese Funktion abgelehnt.

Es gibt im Recordset auch eine Supports-Eigenschaft, in der festgestellt werden kann, ob das Recordset Update/Delete unterstützt.

Im Falle des Updates/Deletes kann ein Fehler ausgelöst werden, dass sich die Daten zwischenzeitlich geändert haben.
Über einen Filter kann man sich diese Sätze dann rausselektieren, da mittels UpdateBatch mehrere Operationen durchgeführt werden können und somit mehrere Sätze betroffen sein können.

Für das Arbeiten mit .NET kannst du die Designer verwenden um komfortabel Queries zu definieren.

PS:
Du solltes zum Arbeiten mit der AS/400 den ODBC-Treiber an Stelle des OLEDB IBMDA400 verwenden (ODBC-Provider von .NET), da dieser mehr Komfort bietet.

Easyrider
13-12-06, 14:19
kay, dann werd ich mal weiterbasteln. Danke für die Hilfe :)

BDehmel
20-06-08, 06:32
Hallo,

in C# ist dieses ohne weiteres möglich:

Die Fill Methode des DataAdapters kann mit den Parametern "Start" und "Anzahl" aufgerufen werden.

Frag mich aber nicht wie perfomant das ist und was intern da passiert.

Gruß Björn