Entwickler-Ecke

Datenbanken - Komplizierte Geschichte mit Oracle9i und ODAC/dbExpress


deefens - Do 23.09.04 22:31
Titel: Komplizierte Geschichte mit Oracle9i und ODAC/dbExpress
Hallo Forumsteilnehmer,

ich brauche für meine Client-Anwendung eine Funktion, die das
Exportieren von Tabellendaten im CSV-Format ermöglicht. Da ein Select
* auf eine sehr große Tabelle dazu führt, dass der Client erstmal
längere Zeit gar nichts macht, wollte ich die Daten in mehreren
Durchläufen abwechselnd auslesen und auf die Platte schreiben.

Ich habe mich Serverseitig bereits schlau gemacht und mir folgenden
Code zurechtgebastelt:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
spool c:\test
declare
  cursor c1 is
    select * from F_VBO_DC_OVERVIEW;
  type t_records is table of F_VBO_DC_OVERVIEW%ROWTYPE;
  records t_records; 
begin
  open c1;
  loop
    fetch c1 BULK COLLECT INTO records LIMIT 5;
    for i in 1..records.count loop
      dbms_output.put_line(records(i).MARKET_SHARE_PYM);
    end loop;
    exit when c1%notfound;
  end loop;
  close c1;
end;
/
spool off


Statt einem Spool in eine Datei will ich aber die Daten zur
Clientanwendung übertragen und dort sequentiell weiterverarbeiten vor
dem Speichern. HAt jemand eine Idee, wie ich das anstellen könnte? Ich
bräuchte sozusagen eine konstante Verbindung zur Datenbank während des
Fetchvorgangs mit Übertragung der Zwischenergebnisse... Als
DAtenbankkomponenten verwende ich die ODAC-Komponente von CoreLab, es
täte aber auch eine Lösung für dbExpress.

Danke für jeden Hinweis!!


Udontknow - Fr 24.09.04 09:20

Hallo,

Oracle ist nun nicht mein Fachgebiet, aber unter Interbase gibt es die Möglichkeit, nur Teildaten zu holen:


Quelltext
1:
select first 100 skip 100 * from Tabelle                    

würde die ersten 100 Datensätze überspringen und die nächsten 100 liefern.

Gibt es vielleicht einen Primärschlüssel, an dem man sich halten könnte? Wenn das z.B. ein Integerfeld wäre, könntest du so vorgehen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
begin
  //Den höchsten vorhandenen Primärschlüsselwert der Tabelle ermitteln
  Dataset.Active:=False;
  Dataset.SQL.Text:='select Max(PrimaryKey) from Tabelle';
  Dataset.Active:=true;
  HighestPrimaryKey:=Dataset.FieldByName('PrimaryKey').AsInteger;

  //Daten holen
  MaxPrimaryKeyFound:=0;
  Repeat
    Dataset.Active:=False;
    Dataset.SQL.Text:='select * from Tabelle where PrimaryKey>'+IntToStr(MaxPrimaryKeyFound)+' and PrimaryKey<'+IntToStr(MaxPrimaryKeyFound+1000)+' order by PrimaryKey';
    Dataset.Active:=True;
    //Den höchsten Primärschlüsselwert im Dataset suchen
    MaxPrimaryKey:=FindMaxPrimaryKeyInDataset;
    //Dataset-Daten speichern
    SaveDatasetToDisk;
  until MaxPrimaryKey=HighestPrimaryKey;
end;


Cu,
Udontknow


deefens - Fr 24.09.04 10:15
Titel: Danke für die Antwort
leider hilft mir deine antwort nicht weiter, da es ein skip-ähnliches statement in oracle nicht gibt. in mysql würde ich einfach die limit-klausel verwenden, aber unter oracle sind selbst solch "billigen" features nicht auszumachen. ich kann mich auch nicht am primärschlüssel orientieren, da ich mich in meinen proggy nicht darauf verlassen kann, dass die jeweilige quelltabelle einen pk definiert hat :( ich hab auch schon überlegt, was mit der rowid anzufangen, aber die ist leider nicht numerisch sondern enthält ausschliesslich buchstaben...

ich bin echt langsam am verzeifeln


Udontknow - Fr 24.09.04 10:20

Zitat:
ich hab auch schon überlegt, was mit der rowid anzufangen, aber die ist leider nicht numerisch sondern enthält ausschliesslich buchstaben...
Auch Strings kann man miteinander vergleichen. Wenn das also eine Art Primärschlüssel ist, na gut, dann eben ein String als Primärschlüssel benutzen.

Cu,
Udontknow


jasocul - Fr 24.09.04 11:27

Es gibt eventuell folgende Möglichkeit bei Oracle:

Quelltext
1:
2:
select * from artikeldaten
where rownum < 100

Was dabei allerdings nicht geht ist folgendes:

Quelltext
1:
2:
select * from artikeldaten
where rownum > 100

Wenn du also den 2ten Block holen willst, gibt es keine einfache Lösung. Ich würde dann evtl mit einem "not in" (in einem Sub-Select) über die RowId arbeiten. Ist allerdings bei sehr großen Datenmenge ziemlich langsam, fürchte ich. Aber vielleicht hilft das als Ansatz.