Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Datenimport ohne Doppelte Daten mit SQL (https://www.delphipraxis.net/176859-datenimport-ohne-doppelte-daten-mit-sql.html)

dUSER.th 1. Okt 2013 08:35

Datenbank: EMS FireBird • Version: 1.5 • Zugriff über: Delphi 7 ZQuery

Datenimport ohne Doppelte Daten mit SQL
 
Hallo zusammen,

Ich habe 2 Tabellen.
Tabelle1 "TB_IMPORT"
wird mit Daten aus *.xls oder *.txt gefüllt.
Tabelle2 "TB_RP2013"
soll mit Daten aus Tabelle1 befüllt werden aber keine schon vorhandenen Daten.
In beiden Tabellen gibt es das Feld "BEWNR" = Bewegnummer was eindeutig ist.

Mein momentaner Ansatz.

Delphi-Quellcode:
 
  DBF2 := ZQuery2;
  DBF3 := ZQuery3;
  vJAHR:= '2013';

  with DBF2 do begin
    SQL.Clear;
    SQL.Text:= 'SELECT '+
                 'TB_IMPORT.GEBUCHT, '+
                 'COUNT(TB_IMPORT.BEWNR) AS DOPPELT, '+
                 'TB_RP'+vJAHR+'.BEWNR '+
                'FROM '+
                'TB_IMPORT '+
                'INNER JOIN TB_RP'+vJAHR+' ON (TB_IMPORT.BEWNR=TB_RP'+vJAHR+'.BEWNR) '+
                'GROUP BY '+
                 'TB_IMPORT.GEBUCHT, '+
                 'TB_RP'+vJAHR+'.BEWNR';
    DBF2.Active:= True;
    Form1.ProgressBar1.Max:= DBF2.RecordCount;
    while NOT DBF2.Eof do begin
      vBEWNR := DBF2.FieldValues['BEWNR'];
      Form1.ProgressBar1.Position:= DBF2.RecNo;

      with DBF3 do begin
        SQL.Clear;
        SQL.Text:= 'UPDATE TB_IMPORT SET GEBUCHT = 1 WHERE '+
                    'TB_IMPORT.BEWNR = ' + vBEWNR;
        DBF3.ExecSQL;
      end;
      Label3.Caption:= IntToStr(DBF2.RecordCount);
      Form1.Repaint;
      DBF2.Next;
    end;
  end;
Es werden alle 2 Stunden cs. 10.000 Daten eingelesen was mit unter sehr langsam ist.
Ich denke, ich hatte das schon mal schneller. Nur leider sind von meiner 1. Version verschiedene Units verloren gegangen. Ich habe nur noch die *.exe Datei aber da finde ich nicht alles.

Habt Ihr eventuell einen hinweis was ich noch ändern sollte oder kann?
Vielen Dank

Morphie 1. Okt 2013 08:42

AW: Datenimport ohne Doppelte Daten mit SQL
 
1. arbeite mit Transaktionen
1.1. damit die Transaktion nicht zu groß wird, kannst du nach X Datensätzen ein commit ausführen. Nach wie vielen Datensätzen genau der richtige Zeitpunkt ist, musst du ausprobieren
2. arbeite mit prepared-statements
2.1. dafür musst du auch mit Parametern arbeiten, statt dir den SQL-Befehl ständig neu zusammenzubasteln...
3. nach jedem Datensatz ein Repaint? Ich würde das Repaint vielleicht nur nach allen 500 Datensätzen oder so durchführen (falls überhaupt erforderlich)

weisswe 1. Okt 2013 08:51

AW: Datenimport ohne Doppelte Daten mit SQL
 
Hallo!

Habe zwar noch nicht mit einer Firebird DB gearbeitet, aber in anderen Datenbanken ist die Syntax so oder so ähnlich:
Code:
insert [felder] into tab2 from
(select [felder] from tab1 alias1 where not exists
 (select [felder] from tab2 where key = alias1.key)
)
Grüße,
Werner

dUSER.th 1. Okt 2013 09:02

AW: Datenimport ohne Doppelte Daten mit SQL
 
Ups das ging aber schnell,

vielen Dank erst mal.

#Morphie
P3. Das anzeigen der RecordCount kommt wieder raus, ist nur momentan zur anzeige.

P1 bis P2.1 komm ich jetzt nicht so ganz mit.
Es soll nur der doppelte Satz mit einem Zeichen markiert werden. Lieber währe es mir ich kann den Satz gleich Löschen. Aber das ist ja warum auch immer noch langsamer.

Könntest Du mir mit P1 mal einen kleinen weiteren Tip geben?

#weisswe

Das hatte ich auch schon durch hierbei brauch die DB ca. 1 Std bei 9400 Sätzen.
Warum auch immer.

Vielen Dank

mkinzler 1. Okt 2013 09:06

AW: Datenimport ohne Doppelte Daten mit SQL
 
U.U. bietet sich hier ein MERGE oder UPDATE OR INSERT an

Morphie 1. Okt 2013 10:17

AW: Datenimport ohne Doppelte Daten mit SQL
 
Zitat:

Zitat von dUSER.th (Beitrag 1230420)
P1 bis P2.1 komm ich jetzt nicht so ganz mit.
Es soll nur der doppelte Satz mit einem Zeichen markiert werden. Lieber währe es mir ich kann den Satz gleich Löschen. Aber das ist ja warum auch immer noch langsamer.

Könntest Du mir mit P1 mal einen kleinen weiteren Tip geben?

P1:
Ich weiß nicht genau wie ZEOS das intern macht, aber ich vermute, wenn du keine Transaktion explizit angibst / erzeugst, erzeugt ZEOS eine Transaktion automatisch.
In deinem Beispiel würde ZEOS automatisch für jeden Datensatz eine eigene Transaktion erzeugen. Das ist natürlich nicht sinnvoll...
Du müsstest dir also zu Beginn der Methode eine Transaktion erzeugen, dem Query zuordnen und am ende (oder zwischendurch) ein Commit (Speichern) der Transaktion durchführen.

P2.1:
Du setzt in jedem Schleifendurchlauf (Datensatz) den Commandtext für DBF3 neu. Den solltest du aber nur einmalig vor der Schleife setzen:
Code:
UPDATE TB_IMPORT SET GEBUCHT = 1 WHERE TB_IMPORT.BEWNR = :PAR_BEWNR;
anschließend ein
Delphi-Quellcode:
DBF3.Prepare;
um den Befehl zur Datenbank zu schicken.
In dem Moment weiß die Datenbank genau, was sie machen soll. Ihr fehlen aber noch die entsprechenden Datensätze / Werte.
Also füllst du jetzt innerhalb der Schleife den Parameter ":PAR_BEWNR" mit deiner Variable vBEWNR und führst ein Execute durch.

Wenn du das so machst, hast du gleich mehrere Vorteile:
1. du verringerst den Traffic zum Datenbankserver.
2. der Server weiß bereits, was er zutun hat, muss den Befehl also nicht jedes Mal neu parsen.
3. du kannst dir so keine SQL-Injections einfangen...

hstreicher 1. Okt 2013 12:08

AW: Datenimport ohne Doppelte Daten mit SQL
 
Zitat:

Zitat von dUSER.th (Beitrag 1230420)
Ups das ging aber schnell,

#weisswe

Das hatte ich auch schon durch hierbei brauch die DB ca. 1 Std bei 9400 Sätzen.
Warum auch immer.

Vielen Dank

ist den ein Index auf das Feld BEWNR angelegt ?

@mkinzler

"update or insert" geht nicht mit seiner 1.5 er Version

Blup 1. Okt 2013 12:35

AW: Datenimport ohne Doppelte Daten mit SQL
 
Wenn es hier im Gegensatz zu Überschrift nur darum geht bereits vorhandene Datensätze zu kennzeichnen, genügt dann nicht ein Befehl an die Datenbank?
Code:
update tb_import a
set   a.gebucht = (select count(b.bewnr) from tb_rp2013 b where (b.bewnr = a.bewnr))
In der Tabelle "tb_rp2013" sollte ein eindeutiger Index auf "bewnr" vorhanden sein.

dUSER.th 1. Okt 2013 16:35

AW: Datenimport ohne Doppelte Daten mit SQL
 
Hallo zusammen,

Stimmt, meine Überschrift zum Thema ist in dem Sinne Falsch.
Sorry mein Fehler ich habe schon zuweit gedacht.

Die Daten die Doppelt sin sollen gekennzeichnet werden.
Einen Index kann ich nicht auf das Feld "BEWNR" legen, weil in der Tabelle TB_RP2013
die Bewegnummer durchaus Doppelt sein kann. Diese habe dann aber einen Präfix.
Und nur die Daten aus der Importtabelle dürfen nicht doppelt vorkommen.
Ist schon etwas verrückt, aber es soll so sein.

Ich hatte jetzt mal den Code von #hstreicher mit den EMS FireBird Manager getestet.
Der Code wurde angenommen aber nach ca. 1 1/2 Std. hat sich mein Server wegen Überhitzung erstmal verabschiedet.
Nun habe ich erst mal Serverprobleme die ich beheben muss und melde mich wieder, wenn alles wieder Funktioniert.

Erst mal Vielen Dank für die Hilfe
bis Später

mkinzler 1. Okt 2013 16:45

AW: Datenimport ohne Doppelte Daten mit SQL
 
Zitat:

Einen Index kann ich nicht auf das Feld "BEWNR" legen, weil in der Tabelle TB_RP2013
die Bewegnummer durchaus Doppelt sein kann.
Das verhindert aber keinen Index


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:38 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz