Seite 1 von 1

DbImport (Erledigt)

Verfasst: Mo, 12. Aug 2019 13:14
von Wolfgang Ciriack
Hallo,
ich möchte Daten aus einer strukturgleichen Datenbank einlesen, aber nur, wenn nicht schon vorhanden (hier z.B. Feld renum)
Ich öffne also die Datenbank, setze den Index und mache einen DBImport, in etwa so:

Code: Alles auswählen

select("opk")
opk->(dbsetorder(1))  /* renum */
opk->(DbImport("ra2018.dbf",,{|| opk->(dbseek(field->renum))=.F.}))
Das klappt so jedoch nicht.
Gibt es eine Möglichkeit, den Codeblock für die ForBedingung so zu setzen, dass das klappt ?
Wird da evtl. eine Variable/Datensatzobjekt an den Codeblock übergeben ?

Re: DbImport

Verfasst: Mo, 12. Aug 2019 14:07
von brandelh
Dein Codeblock muss vor jedem Einlesen einen dbseek in der Ziel Datei machen, das wird langsam, auf welche DBF sich FIELD bezieht könnte ich jetzt gar nicht sagen.
Gibt es einen Syntax Error oder reagiert es nur nicht wie erwartet ?
Ist die Ziel Datei exclusive offen ?

PS: ich meide diesen hoch komplexen Funktionen, weil ich nie genau weiß, was intern abgeht.
Ich würde das aufteilen in eine do while der einzulesenden Datei, dann ein DBSeek in der Zieldatei und falls benötigt scatter gather und Satz einfügen.

Re: DbImport

Verfasst: Mo, 12. Aug 2019 15:24
von Tom
Wie kommst Du darauf, dass die einzulesende Tabelle in einer Workarea mit dem Alias "Field" geöffnet wird, Wolfgang? Bei mir funktionieren ähnliche Konstrukte ohne Alias an dieser Stelle:

Code: Alles auswählen

DbImport('import.dbf',,{||!import}) // "import" ist ein Feld in import.dbf und regelt, ob importiert werden soll

Re: DbImport

Verfasst: Mo, 12. Aug 2019 16:12
von Wolfgang Ciriack
Hubert,
ja mit einer Schleife wäre die weitere Vorgehensweise von mir,.
Tom,
ja, wenn ich ein Feld hätte, von dem der Import abhängig wäre, würde dein Beispiel klappen. Ich muss aber bei jedem Satz schauen, ob die z.B. die Rechnungsnummer im Ziel schon vorhanden ist, d.h. ein dbseek machen und dann entscheiden, ob Import oder nicht.

Dann werde ich wohl doch eine Schleife bauen müssen. :(

Re: DbImport

Verfasst: Mo, 12. Aug 2019 16:30
von Jan
Wolfgang,

wenn Du eine Schleife daraus machst kannst Du das ja sehr schnell mit Scatter und Gather machen. Du hattest ja geschrieben das die beiden Tabellen strukturgleich sind. Damit sind das dann nur fünft Zeilen Code für die Schleife inkl. dem Übertragen der Daten (+ Deine Abfrage ob schon vorhanden). Das ist einfacher geworden mit dem Update zu GATHER und SCATTER vor einigen Monaten.

Code: Alles auswählen

DO WHILE .NOT. tabelle1_>(EoF())
   SCATTER NAME oData IN tabelle1
   tabelle2->(DbAppend())
   GATHER NAME oData IN tabelle2
ENDDO
Jan

Re: DbImport

Verfasst: Di, 13. Aug 2019 8:05
von brandelh
Je nach Anzahl der Datensätze könntest du die Kennummern der schon vorhandenen Datensätze speichern (Array oder String: "*Such1*Such2*") und dann in der Routine abfragen.
Das dauernde Satzanfang, seek und Append (Dateiende) zwingt eine Festplatte in die Knie.

Re: DbImport

Verfasst: Di, 13. Aug 2019 9:20
von Tom

Code: Alles auswählen

opk->(DbImport("ra2018.dbf",,{||!NumberExists(renum)}))

FUNCTION NumberExists(n)
opk->(DbSeek(n))
RETURN !opk->(EoF())

Re: DbImport

Verfasst: Di, 13. Aug 2019 11:35
von Tom
Das mit dem Array ist eine gute Idee:

Code: Alles auswählen

LOCAL aNums := {}
use ra2018 new
DbEval({||aAdd(aNums(renum))})
close
opk->(DbImport("ra2018.dbf",,{||!renum $ aNums}))

Re: DbImport

Verfasst: Di, 13. Aug 2019 12:55
von Wolfgang Ciriack
Hallo Tom,
danke für deinen Vorschlag, hatte das jetzt schon vor deinem Beitrag auch so gelöst:

Code: Alles auswählen

opk->(DbImport("RA2018.dbf",,{|| CheckVorhanden(field->renum)}))
**********************************************
static function CheckVorhanden(wert)
return !opk->(dbseek(wert))

Re: DbImport (Erledigt)

Verfasst: Di, 13. Aug 2019 13:33
von Tom
Das mit dem Array ist aber eigentlich noch cooler. Und performanter, je nach Tabellengröße.