Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Einfügen über externalTabelle funktioniert nicht richtig (https://www.delphipraxis.net/179327-einfuegen-ueber-externaltabelle-funktioniert-nicht-richtig.html)

blutigerAnfänger 27. Feb 2014 08:59

Datenbank: firebird • Version: 2 • Zugriff über: IB Komponente

Einfügen über externalTabelle funktioniert nicht richtig
 
Hallo

ich möchte eine external Tabelle in eine Firebird Tabelle überführen. Der Quelltext den ich mir zusammengestückelt habe funktioniert fehlerfrei(laut Compiler). Das Ergebnis ist niederschmetternd.

Es gibt keine Feldtrennung, jeweils 2 Buchstaben verschwinden(egal ob Feld1 od.Feld2), Datensatzendezeichen werden nicht erkannt.
Delphi-Quellcode:
procedure TForm1.btn2Click(Sender: TObject);
begin
//IBDatabase1.DatabaseName := 'c:\db\test.fdb';
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'DROP TABLE tabelle2' ;
      Active:=true;
      IBTransaction1.Commit;
      sql.clear;
      Active:=false;
      sql.text := 'CREATE TABLE TABELLE2 (FELD001 VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE DE_DE, FELD002 VARCHAR(250) CHARACTER SET ISO8859_1 COLLATE DE_DE)';
      Active:=true;
      IBTransaction1.Commit;
   end;
ibdb1.Close;
end;


procedure TForm1.btn3Click(Sender: TObject);
begin
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'Create TABLE dat_ext external file''c:\externalTables\Tabelle2.txt''(feld001 varchar(50),feld002 varchar(250), crlf smallint )';
      Active:=true;
      IBTransaction1.Commit;
   end;
end;

procedure TForm1.btn4Click(Sender: TObject);
begin
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'Insert into Tabelle2 SELECT FELD001 , FELD002  from dat_ext ';
      Active:=true;
      IBTransaction1.Commit;
   end;
end;

procedure TForm1.btn5Click(Sender: TObject);
begin
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'drop table dat_ext ';
      Active:=true;
      IBTransaction1.Commit;
   end;
end;
Der Quelltext sieht zwar nicht sehr vertrauenserweckend aus, aber er läuft.

Ich habe mehrere Möglichkeiten für crlf gefunden, hier als smallint aber auch char(2) ist möglich. Verwirrend!
Code:
  ... TABLE dat_ext external file''c:\externalTables\Tabelle2.txt''(feld001 varchar(50),feld002 varchar(250), crlf smallint )';
Völlig egal ob smallint oder Char(2), das Ergebnis ist dasselbe.

Ich hoffe ihr könnt mir helfen.

jobo 27. Feb 2014 09:23

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Kann man bei firebird keine Zeilentrennzeichen definieren?
Weißt Du, welche es wirklich sind? Stammt das File aus einem Unix oder (Win-)DOS System?
Würde ich mal mit Hex Editor untersuchen und das Manual von external Tables studieren.

borwin 27. Feb 2014 10:21

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
... so auf die Schnelle eine Hinweiss.
Der Import verlangt immer feste Längen. Das geht am besten mit CHAR Feldern.
Dort werden immer Werte mit der definierten Länge eingetragen. Rest wird mit Leerzeichen aufgefüllt
Auch das Feld crlf muss ein Charfeld sein.

Gruß
Borwin

Perlsau 27. Feb 2014 12:09

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
@blutigerAnfänger:

Ich hab da ein paar Fragen zu deinem Problem:

1. Was ist eine "external Tabelle"? Meinst du eine Tabelle in einem anderen DMBS?

2. Wenn sich diese "external Tabelle" in einem anderen DMBS befindet, kannst du mit deiner Delphi-Anwendung darauf zugreifen?

3. Wenn sich diese "external Tabelle" in einem anderen DMBS befindet, kannst du mit einem entsprechenden Dateimanager diese Tabelle exportieren, z.B. als CSV-Datei?

4. Wieso verwendest du in deiner Anwendung nicht aussagekräftige Bezeichner? Button1 sagt überhaupt nichts darüber aus, wozu der Button verwendet wird. Dasselbe gilt für deine Spalten-Bezeichner in der Datenbank. Durch die Verwendung sog. sprechender Bezeichner erhöhst du die Übersicht und Lesbarkeit deines Quellcodes.

Perlsau 27. Feb 2014 12:13

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von borwin (Beitrag 1249815)
... so auf die Schnelle eine Hinweiss.
Der Import verlangt immer feste Längen. Das geht am besten mit CHAR Feldern.
Dort werden immer Werte mit der definierten Länge eingetragen. Rest wird mit Leerzeichen aufgefüllt
Auch das Feld crlf muss ein Charfeld sein.

Verstehe ich nicht: Wenn ich in Firebird Daten aus einem anderen DMBS importieren muß, mache ich das mit einem SQL-Script, entweder direkt aus der Delphi-Anwendung heraus oder eben mit IbExpert (kostenlos in der Personal-Version). Da braucht's kein Auffüllen mit Leerzeichen; die Daten werden genau so in die Firebird-DB eingetragen, wie sie im Quell-DMBS vorliegen.

mkinzler 27. Feb 2014 12:13

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

1. Was ist eine "external Tabelle"? Meinst du eine Tabelle in einem anderen DMBS?
Eine externe Datei, welche wie als Tabelle eingebunden wird und auf die man per SQL-Befehle (meist lesend) zugreifen kann.

Perlsau 27. Feb 2014 12:17

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von mkinzler (Beitrag 1249839)
Zitat:

1. Was ist eine "external Tabelle"? Meinst du eine Tabelle in einem anderen DMBS?
Eine externe Datei, welche wie als Tabelle eingebunden wird und auf die man per SQL-Befehle (meist lesend) zugreifen kann.

Du meinst, man kann in eine Firebird-DB eine externe Datei einbinden, die dann von der Anwendung, die auf diese Datenbank zugreift, als gewöhnliche Tabelle angesehen wird?

mkinzler 27. Feb 2014 12:20

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Jein, man kann mit dieser Tabelle nicht alles machen; es gibt bestimmte Einschränkungen

Perlsau 27. Feb 2014 12:31

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von mkinzler (Beitrag 1249844)
Jein, man kann mit dieser Tabelle nicht alles machen; es gibt bestimmte Einschränkungen

Und schon wieder was dazugelernt: Von diesen external Tables hatte ich bislang noch nichts gehört. Nun hab ich aber einen (älteren) Text gefunden, der das erklärt.

blutigerAnfänger 27. Feb 2014 13:30

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
In der Zwischenzeit habe ich mir IBExpertPersonal aufgespielt und festgestellt:
1. Die externe Datei wird erstellt und befüllt.
2. Die Zieltabelle (Tabelle2) wird ordnungsgemäß befüllt(mit dem Mist der in der externen Datei steht.)

Zu 1. habe ich ein schematisches Beispiel:
original
Code:
AAAAA  {45 Leerzeichen}  BBBBB {245 Leerzeichen}  Zeilenende
in externer Datei
Code:
AAA   {43 Leerzeichen}   BB {8 Leerzeichen} Spaltentrenner(IBExpert) B {240 Leerzeichen}  Zeilenende

A steht für den zB.Buchstaben aus dem String in Feld 1
B analog
Wie man an der Zahl der As und Bs erkennt werden Buchstaben verschluckt.

Also ist offensichtlich bei der Überführung in die externe Datei bereits ein Fehler aufgetreten.
Mir ist aber keine andere Möglichkeit bekannt um mit externen Dateien zu arbeiten.

Perlsau 27. Feb 2014 13:42

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von blutigerAnfänger (Beitrag 1249864)
AAA {43 Leerzeichen} BB {8 Leerzeichen} Spaltentrenner(IBExpert) B {240 Leerzeichen} Zeilenende

Das läßt vermuten – gerade auch, weil die Anzahl der Zeichen ja übereinstimmt (245+5=250 / 240+8+2=250) –, daß im Record in dieser Spalte ein Spaltentrennzeichen vorkommt, das eigentlich noch zum Feldinhalt gehören sollte. Dieses Spaltentrennzeichen wird dann wohl korrekterweise fehlinterpretiert. Wenn du z.B. einen Inhalt hast, in welchem z.B. das ; vorkommt, das aber gleichzeitig Spaltentrennzeichen ist, ist das Chaos vorprogrammiert. Vielleicht könntest du das Spaltentrennzeichen ändern, müßtest das dann aber auch in der Quelldatei machen.

blutigerAnfänger 27. Feb 2014 14:01

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Code:

AAA  {43 Leerzeichen}   BB {8 Leerzeichen} Spaltentrenner(IBExpert) B {240 Leerzeichen}  Zeilenende

A steht für den zB.Buchstaben aus dem String in Feld 1
B analog
das ist die allererste Zeile der external Tabelle. Es fehlen bereits 2 Buchstaben aus dem String A (Feld 1)

@ Perlsau
Der Gedanke mit dem Trennzeichen ist gut, dennoch wo sollen bei den 2 fehlenden Buchstaben in der allerersten Zeile Trennzeichen herkommen?

In den Vorschriften zur external Datei sollen Dateien mit fester Feldlänge verwendet werden. Genau das habe ich. Was in Feld 2 (mit BB gekennzeichnet) an fehlinterpretierbaren Trennzeichen stehen könnten, sollte durch die FeldGröße (250 Zeichen) aufgefangen werden.

Perlsau 27. Feb 2014 14:12

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Du hattest oben doch geschrieben:
Code:
AAAAA {45 Leerzeichen}  BBBBB {245 Leerzeichen}  Zeilenende
Das heißt, du hast 5 Zeichen an Information, die mit den 245 Leerzeichen dahinter 250 Zeichen ergeben. Insgesamt hast du hier zwei Spalten.

Nun hast du eine Zeile, in welcher sich plötzlich drei Spalten befinden, wobei die Gesamtanzahl der Länge der letzten beiden Spalten wiederum genau die 250 Zeichen ergeben. Das heißt: irgendwo in dieser Zeile steht ein Spaltentrennzeichen, das dort nicht hingehört, weshalb auch eine dritte Spalte (fehl-)interpretiert wird. Würde dort kein Spaltentrennzeichen stehen, dann würde die Zeile korrekt interpretiert werden.

Zitat:

Zitat von blutigerAnfänger (Beitrag 1249877)
Der Gedanke mit dem Trennzeichen ist gut, dennoch wo sollen bei den 2 fehlenden Buchstaben in der allerersten Zeile Trennzeichen herkommen?

Welche zwei fehlenden Buchstaben? Ich kann dazu nichts sagen, weil mir deine externe Datei nicht vorliegt bzw. weil du den Inhalt der problematischen Zeile nicht bekannt gibst. Das heißt, ich weiß weder, was genau in dieser Zeile steht, noch weiß ich, wie das Trennzeichen (das ja auch aus mehreren Zeichen bestehen kann) aussieht.

Trennzeichen kommen nicht von irgendwo her, sondern befinden sich in deiner externen Datei. Wenn ich derartige Probleme habe, dann untersuche ich die entsprechende Datei ganz genau, am besten via Debugging im Quellcode meines verarbeitenden Programms.

blutigerAnfänger 27. Feb 2014 17:18

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Liste der Anhänge anzeigen (Anzahl: 2)
@Perlsau
Also in Datei Tabelle2.txt steht meine originale TestTabelle.
In Tabelle2export.txt ist die External Tabelle als Insert statement.(von IBExpert exportiert)
Ich hoffe es hilft dir weiter.
Wo in der exportierten Tabelle allerdings die Kommas herkommen wird wohl ein Geheimnis von Firebird bleiben. Ich vermute mal, daß sollen die ominösen Trennzeichen sein, welche nicht in der Original Datei vorhanden sind.

Perlsau 27. Feb 2014 17:49

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von blutigerAnfänger (Beitrag 1249907)
@Perlsau
Also in Datei Tabelle2.txt steht meine originale TestTabelle.
In Tabelle2export.txt ist die External Tabelle als Insert statement.(von IBExpert exportiert)
Ich hoffe es hilft dir weiter.
Wo in der exportierten Tabelle allerdings die Kommas herkommen wird wohl ein Geheimnis von Firebird bleiben. Ich vermute mal, daß sollen die ominösen Trennzeichen sein, welche nicht in der Original Datei vorhanden sind.

Wenn ich mir die originale Tabelle anschaue, komme ich zu dem Schluß, daß es sich um eine ganz normale Textdatei handelt. Die erste Spalte ist immer 50 Zeichen lang, die zweite geht bis zum Linebreak. Da böte es sich doch an, diese Textdatei via Stringliste einzulesen, danach durchzuiterieren und dabei die jeweils ersten 50 Zeichen jedes Items als Inhalt der Spalte 1 (Fremdwort) zu kopieren. Der Rest ist die Beschreibung des Fremdworts (ungetestet, daher ohne Garantie):
Delphi-Quellcode:
Procedure Einlesen;
Var
  MeineListe : TStringList;
  Datei,
  Fremdwort,
  Beschreibung : String;
  i,z : Integer;

Begin
  If not OpenDialog.Execute then exit;
  Datei := OpenDialog.FileName;
  MeineListe := TStringList.Create;

  Try
    MeineListe.LoadFromFile(Datei);
    z := MeineListe.Count;

    If z > 0 then
    For i := 0 to z-1 DO
    Begin
      Beschreibung := Liste[i];
      Fremdwort := Trim(Copy(Beschreibung,1,50);
      Delete(Beschreibung,1,50);

      DatenModul.Dataset.Append;
      DatenModul.Dataset.FieldByName('FREMDWORT').AsString := Fremdwort;
      DatenModul.Dataset.FieldByName('BESCHREIBUNG').AsString := Beschreibung;
      DatenModul.Dataset.Post;
    End;
  Finally
    MeineListe.Free;
  End;

  ShowMessage('Einlesen von "' + Datei + '" beendet ...');
End;
In der Original-Textdatei kommen etliche Kommas vor. Wenn die als Trennzeichen fungieren, kann das natürlich nicht klappen.

Wie hattest du denn mit IbExpert die externe Datei eingebunden?

blutigerAnfänger 27. Feb 2014 18:34

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Ich benutze IBExpert eigentlich nur um Ergebnisse anzusehen, die von Delphi Quelltext erzeugt wurden.

Nun eine Frage zu deinem Quelltext: Datenmodul?? Steht in den Interbasekomponenten nicht drin.

Offenbar willst du jetzt einen anderen Weg als externalFile einschlagen?

Perlsau 27. Feb 2014 18:48

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von blutigerAnfänger (Beitrag 1249918)
Nun eine Frage zu deinem Quelltext: Datenmodul?? Steht in den Interbasekomponenten nicht drin.

Ein Datenmodul ist ein Container für Datenzugriffs-Komponenten. Du kannst ein neues Datenmodul genau so anlegen, wie du z.B. eine neue Form anlegst. Ich verwende das Datenmodul aber auch für die meisten Methoden, die mit dem direkten Datenzugriff zu tun haben. Natürlich mußt du deine Datenzugriffs-Komponenten nicht in einem Datenmodul unterbringen.

Zitat:

Zitat von blutigerAnfänger (Beitrag 1249918)
Offenbar willst du jetzt einen anderen Weg als externalFile einschlagen?

Ich hab keine Ahnung, welchen Weg du gegangen bist, um den Inhalt der Textdatei in deine Firebird-Datenbank zu bekommen, doch ganz offensichtlich war diese Methode fehlerhaft. Daher habe ich dir eine ganz einfache, übersichtliche Vorgehensweise gezeigt. Ob du das übernimmst oder dir was anderes überlegst, bleibt dir überlassen.

Es geht ja offenbar nicht darum, eine externe Datei zur ständigen Verfügung zu haben, wie das z.B. beim Einbinden einer external Table beabsichtigt ist, sondern um das Einlesen von Daten aus einer Textdatei in die Datenbank. Vermutlich willst du dir ein datenbankgestütztes Fremdwörterbuch bauen und dafür bereits vorhandene Fremdwort-Ressourcen verwenden. Das heißt, du willst die Inhalte nur einmal einlesen, danach benötigst du diese Textdatei nicht mehr. Anders wäre es, wenn du das ExternalFile benötigen würdest, weil irgend eine andere Anwendung diese External Table ständig aktualisiert. Bei External Table werden, soweit ich das verstanden habe, keine Kopien der Inhalte in der Datenbank angelegt, sondern das ExternalFile direkt als Speicher verwendet. Du aber möchtest die Daten der Textdatei in deiner Datenbank-Tabelle verfügbar haben.

Übrigens fehlt in meiner Methode noch eine Prüfung, ob das aktuell einzufügende Fremdwort bereits in der Datenbank existiert.

blutigerAnfänger 27. Feb 2014 19:22

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von Perlsau (Beitrag 1249921)
Ein Datenmodul ist ein Container für Datenzugriffs-Komponenten. Du kannst ein neues Datenmodul genau so anlegen, wie du z.B. eine neue Form anlegst. Ich verwende das Datenmodul aber auch für die meisten Methoden, die mit dem direkten Datenzugriff zu tun haben. Natürlich mußt du deine Datenzugriffs-Komponenten nicht in einem Datenmodul unterbringen.

Damit werde ich mich erst einmal eine Weile beschäftigen müssen.

Zitat:

Zitat von Perlsau (Beitrag 1249921)

Es geht ja offenbar nicht darum, eine externe Datei zur ständigen Verfügung zu haben, wie das z.B. beim Einbinden einer external Table beabsichtigt ist, sondern um das Einlesen von Daten aus einer Textdatei in die Datenbank. Vermutlich willst du dir ein datenbankgestütztes Fremdwörterbuch bauen und dafür bereits vorhandene Fremdwort-Ressourcen verwenden. Das heißt, du willst die Inhalte nur einmal einlesen, danach benötigst du diese Textdatei nicht mehr. Anders wäre es, wenn du das ExternalFile benötigen würdest, weil irgend eine andere Anwendung diese External Table ständig aktualisiert. Bei External Table werden, soweit ich das verstanden habe, keine Kopien der Inhalte in der Datenbank angelegt, sondern das ExternalFile direkt als Speicher verwendet. Du aber möchtest die Daten der Textdatei in deiner Datenbank-Tabelle verfügbar haben.

Wenn ich dich richtig verstanden habe, unterliegst du offenbar einem Irrtum. Es geht nicht darum, eine externe Datei zur ständigen Verfügung zu haben, sondern um das schnelle Einlesen von Daten (vielleicht ist Bulk Insert dazu das richtige Stichwort). Im Rahmen meiner Recherche habe ich irgendwo gelesen, daß die Orignale Textdatei(mit fixer Datensatzlänge) sozusagen als Block in die ExterneFirebirdTabelle übernommen wird. Daraufhin wird diese ExterneFirebirdTabelle in eine interne Tabelle verwandelt und die externe gelöscht.
Kurz gesagt es ist ein schnellerer Datenimport als das Einlesen jedes einzelnen Datensatzes per Insert...value...

Perlsau 27. Feb 2014 19:41

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von blutigerAnfänger (Beitrag 1249927)
Zitat:

Zitat von Perlsau (Beitrag 1249921)
Es geht ja offenbar nicht darum, eine externe Datei zur ständigen Verfügung zu haben, wie das z.B. beim Einbinden einer external Table beabsichtigt ist, sondern um das Einlesen von Daten aus einer Textdatei in die Datenbank. Vermutlich willst du dir ein datenbankgestütztes Fremdwörterbuch bauen und dafür bereits vorhandene Fremdwort-Ressourcen verwenden. Das heißt, du willst die Inhalte nur einmal einlesen, danach benötigst du diese Textdatei nicht mehr. Anders wäre es, wenn du das ExternalFile benötigen würdest, weil irgend eine andere Anwendung diese External Table ständig aktualisiert. Bei External Table werden, soweit ich das verstanden habe, keine Kopien der Inhalte in der Datenbank angelegt, sondern das ExternalFile direkt als Speicher verwendet. Du aber möchtest die Daten der Textdatei in deiner Datenbank-Tabelle verfügbar haben.

Wenn ich dich richtig verstanden habe, unterliegst du offenbar einem Irrtum. Es geht nicht darum, eine externe Datei zur ständigen Verfügung zu haben, sondern um das schnelle Einlesen von Daten (vielleicht ist Bulk Insert dazu das richtige Stichwort).

Aber genau das schrieb ich oben doch! Der Grund, eine External Table einzubinden, kann nur der sein, eine externe Datei zur ständigen Verfügung zu haben. Mit deinem Hinweis im ersten Post plus der Bemerkung von mkinzler ist bei mir erstmal dieser Eindruck entstanden. Dann habe ich realisiert, daß es dir lediglich "um das Einlesen von Daten aus einer Textdatei in die Datenbank" geht.

Bulk Insert bedeutet nichts anderes, als die Daten in einem Rutsch einzulesen. Das kannst du z.B. auch mit IbExpert machen, wenn du aus den Quelldaten zuvor eine entsprechende SQL-Datei erzeugst.

Delphi-Quellcode:
MeineListe[i] := "insert into Fremdworttabelle (Fremdwort, Beschreibung) values (' + QuotedStr(Fremdwort) + ',' + QuotedStr(Beschreibung) + ');
Und am Ende vor dem Freigeben der Liste:
Delphi-Quellcode:
MeineListe.SaveToFile(Datei + '.sql');
Am Ende hast du eine Textdatei, die du direkt in IbExpert via Sql-Script einlesen kannst.

Kurz: Es gibt viele Wege, um diese Daten in die Datenbank zu bekommen. Einen davon hab ich dir gezeigt.

Zitat:

Zitat von blutigerAnfänger (Beitrag 1249927)
Im Rahmen meiner Recherche habe ich irgendwo gelesen, daß die Orignale Textdatei(mit fixer Datensatzlänge) sozusagen als Block in die ExterneFirebirdTabelle übernommen wird. Daraufhin wird diese ExterneFirebirdTabelle in eine interne Tabelle verwandelt und die externe gelöscht.
Kurz gesagt es ist ein schnellerer Datenimport als das Einlesen jedes einzelnen Datensatzes per Insert...value...

Kannst du mir diese Quelle zeigen, in der beschrieben wird, wie man eine reine Textdatei ohne SQL-Befehle in die Datenbank einliest? Davon hab ich bis heute nämlich noch nie was gehört oder gelesen. Mit External Table hat das, soweit ich das beurteilen kann, aber erstmal nichts zu tun.

Könntest du vielleicht noch mitteilen, wieviele Datensätze insgesamt eingelesen werden sollen? Wenn es wirklich nur ein paar (tausend) sind, dann ist Bulk Insert quasi überdimensioniert. Meine oben gezeigte Methode würde dann vollkommen ausreichen. Bulk Insert hat zudem den Nachteil, daß du nicht ohne weiteres prüfen kannst, ob ein entsprechender Datensatz bereits existiert.

blutigerAnfänger 27. Feb 2014 20:50

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
@Perlsau
Also ich kann dir leider keine Quelle zeigen, dennoch bin ich mir sicher ähnliches gelesen zu haben.(Altersstarrsinn??)
Ansonsten habe ich ja jetzt Material für ein paar Tage. Gute Nacht.

DeddyH 28. Feb 2014 07:46

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von Perlsau (Beitrag 1249931)
Kannst du mir diese Quelle zeigen, in der beschrieben wird, wie man eine reine Textdatei ohne SQL-Befehle in die Datenbank einliest?

Firebird: http://www.firebirdfaq.org/faq209/
MySQL: http://www.little-idiot.de/mysql/mysql-121.html
Oracle: http://docs.oracle.com/cd/B10500_01/...96652/ch12.htm
Weiter habe ich jetzt nicht recherchiert. Das hat mit ständiger Verfügbarkeit usw. überhaupt nichts zu tun, sondern es geht tatsächlich um das schnelle Einlesen größerer Datenmengen aus einer externen Quelle. Auf der Zielseite braucht man natürlich SQL, aber für diesen Zweck ist es eben eine spezielle Syntax.

Perlsau 28. Feb 2014 08:19

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Danke, DeddyH, das erweitert meinen Horizont. :thumb:

blutigerAnfänger 1. Mär 2014 12:36

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Hallo

@Perlsau #19
Du wolltest wissen, um wieviele Datensätze es geht: 100.000 Stck. und mehr.
Dein Quelltext in Abwandlung funktioniert einwandfrei und rasendschnell. Wesentlich langsamer ist das Einlesen des SQL Scripts in IBExpert. Ich habe das mit der kompletten Tabelle ausprobiert und IBExpert benötigt 3 Minuten zum Einlesen von ca.100.000 Datensätzen.

Delphi-Quellcode:
Procedure TForm1.Einlesen();
Var
  MeineListe,
  HilfsListe,
  ZielListe : TStringList;
  Datei,
  Fremdwort,
  Beschreibung : String;
  i,z : Integer;

Begin
  MeineListe := TStringList.Create;

 Try
    MeineListe.LoadFromFile('kurz.txt');
    z := MeineListe.Count;
    ZielListe:= TStringList.Create;
    HilfsListe:= TStringList.Create;
    try
    For i := 0 to z-1 DO
    Begin
    HilfsListe.Text := StringReplace(MeineListe[i], #9, sLineBreak, [rfReplaceAll]);
      Beschreibung := HilfsListe[1];
      Fremdwort := HilfsListe[0];
    ZielListe.Add('Insert into Tabelle2 (Fremdwort,Beschreibung) values (' + QuotedStr(HilfsListe[0]) + ',' + QuotedStr(HilfsListe[1]) + ');');
    end;

  Finally
    MeineListe.Free;
    ZielListe.SaveToFile('ziel.sql');
    HilfsListe.Free;
    ZielListe.Free;

  End;
finally
end;
end;
Gibt es eine Möglichkeit, außerhalb der ZEOS Komponenten welche ich nicht nutze, den Script einzulesen und auszuführen?.

Delphi-Quellcode:
procedure TForm1.LadezielsqlClick(Sender: TObject);
begin
   with IBQuery1 do
    begin
       Active:=False;
       SQL.Clear;
       SQL.LoadFromFile('ziel.sql');
       ExecSQL;
       IBTransaction1.Commit;
    end;
end;
Hier hab bereits nach der ersten Zeile Error Code -104 Token unknown -line 2, Column 1 Insert.



Ach im Übrigen wir sind jetzt sehr weit weg von meiner Ausgangsfrage.

blutigerAnfänger 2. Mär 2014 17:17

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Hallo

@Perlsau
Nach der Neuinstallation der IBX Komponenten, habe ich jetzt die IBScript Komponente zur Verfügung. Und damit folgende Lösung erbastelt.

Delphi-Quellcode:
procedure TForm1.LadezielsqlClick(Sender: TObject);
var
  startzeit,
  stopzeit : TDateTime;
  i:Integer;
begin
startzeit :=Now;
ibdb1.Open;
IBScript.Script.LoadFromFile('ziel.sql');
IBScript.ExecuteScript;
IBTransaction1.Commit;
stopzeit :=Now;
Panel1.Caption :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ;
end;
Um meine 100.000 Datensätze einzulesen, brauche ich jetzt ca. 2,5 Minuten. IBExpert brauchte 3 Minuten.

Nochmals external Tabellen:

Nach langen Herumprobieren hab ich die Lösung:

Falsch ist:
Delphi-Quellcode:
procedure TForm1.btn3Click(Sender: TObject);
begin
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'Create TABLE dat_ext external file''c:\externalTables\Tabelle2.txt''(feld001 varchar(50), FELD002 VARCHAR(250), crlf char(2) )';
      Active:=true;
      IBTransaction1.Commit;
   end;
end;
Richtig ist:
Delphi-Quellcode:
procedure TForm1.btn3Click(Sender: TObject);
begin
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'Create TABLE dat_ext external file''c:\externalTables\Tabelle2.txt''(feld001 char(50), FELD002 CHAR(250), crlf char(2) )';
      Active:=true;
      IBTransaction1.Commit;
   end;
end;
Der Unterschied: char statt varchar.

Zeitliche Verbesserung des Datenimports: SQLScript : 2,5 Minuten, ExternalTabelle : weniger als 5 Sekunden.

Dank an Borwin der das schon in #3 erkannt hat.

Dennoch, auf diese Art und Weise habe ich eine weitere Importmöglichkeit, InsertScript, in Erstellung und Nutzung kennengelernt.
Danke Perlsau.

blutigerAnfänger 7. Sep 2014 21:37

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Erneut external Dateien


Delphi-Quellcode:
procedure TForm1.btn3Click(Sender: TObject);
begin
  with IBQuery1 do
   begin
      Active:=False;
      sql.Clear;
      sql.Text := 'Create TABLE dat_ext external file''c:\externalTables\Tabelle2.txt''(feld001 char(50), FELD002 CHAR(250), crlf char(2) )';
      Active:=true;
      IBTransaction1.Commit;
   end;
end;
Dies ist der richtige Code für die Erstellung eines external Files, bestehend aus 2 Spalten von Strings.

Frage: Wie sieht der Code aus für 4 Spalten, bestehend aus 2 Spalten Strings, 1er Spalte Integer und 1er Spalte ID (Autoinc)?

Mittlerweile habe ich diesen fehlerhaften Code:
Delphi-Quellcode:
      sql.Clear;
      sql.Text := 'Create TABLE dat_ext external file''c:\db\import.txt''(  checkbox integer ,name CHAR(50), bezeichnung CHAR(250), crlf CHAR(2) )';
      Active:=true;
      IBTransaction1.Commit;
      Active:=False;
      sql.Clear;
      sql.Text := 'Insert into Tabelle2 SELECT checkbox , name, bezeichnung from dat_ext ';
      Active:=true;
      IBTransaction1.Commit;
Soweit wie ich inzwischen weiß, wird die Spalte ID(Autoinc) erst nach dem Import der Daten ausgefüllt. Die Tabelle muß aber diese Spalte enthalten.

Code:
      sql.text := 'CREATE TABLE Tabelle2 (checkbox INTEGER, name VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE DE_DE, bezeichnung VARCHAR(250) CHARACTER SET ISO8859_1 COLLATE DE_DE , ID INTEGER)';
Fehler: da kann ich sagen siehe Beitrag #10
Kann Firebird externalFiles überhaupt mit Integer Feldern erstellen? Es sind viele teils widersprüchliche Ergebnisse zu finden, nur großteils Englisch.
Ich hoffe auf Eure Hilfe.

Dejan Vu 8. Sep 2014 06:55

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Externe Tabellen sind nicht dazu da, die Daten in einer endgültigen Form zu enthalten. Sie dienen nur zum Import. Du beschreibst also mit dem 'CREATE TABLE' nur den Aufbau deiner Datei und importierst sie dann in eine andere Tabelle, wobei Du die notwendigen Transformationen vornimmst (Char => Integer, Float, DateTime etc.). Aus diesem Grund ist es auch überflüssig und falsch, einen Autoinc Wert in der externen Tabelle vorhalten zu wollen.

blutigerAnfänger 8. Sep 2014 08:35

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von Dejan Vu (Beitrag 1271506)
..., wobei Du die notwendigen Transformationen vornimmst (Char => Integer, Float, DateTime etc.). Aus diesem Grund ist es auch überflüssig und falsch, einen Autoinc Wert in der externen Tabelle vorhalten zu wollen.

Notwendige Transformationen sind das Stichwort.
String --> CHAR --> VARCHAR
INTEGER --> ??? --> INTEGER

Also Ich habe eine Tabelle mit 3 Feldern (Integer, String, String). Die Stringfelder werden als CHAR bezeichnet und in der endgültigen Firebird Tabelle zu VARCHAR transformiert. Wie mache ich das mit Integer?
INTEGER zu CHAR gibt es Konversionsfehler und INTEGER mit Längenbezeichnung zB. INTEGER(10) ist Blödsinn.

jobo 8. Sep 2014 08:41

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von Dejan Vu (Beitrag 1271506)
Externe Tabellen sind nicht dazu da, die Daten in einer endgültigen Form zu enthalten. Sie dienen nur zum Import. Du beschreibst also mit dem 'CREATE TABLE' nur den Aufbau deiner Datei und importierst sie dann in eine andere Tabelle, wobei Du die notwendigen Transformationen vornimmst (Char => Integer, Float, DateTime etc.). Aus diesem Grund ist es auch überflüssig und falsch, einen Autoinc Wert in der externen Tabelle vorhalten zu wollen.

:thumb:

Ich möchte noch ergänzen, dass das Bedürfnis nach einer eindeutigen ID natürlich legitim ist. Was und wie Du aber auch immer importierst, die zu importierenden Daten sollten über solch ein eindeutiges Merkmal bereits verfügen, notfalls über mehrere Felder und idealer Weise auch gegenüber den bereits importierten Daten. Ansonsten holst Du Dir die Leichen reihenweise in den Keller.

Schau Dir mal Literatur zum Thema ETL an. Ganz grob:
Daten temporär in der DB bereitstellen (z.B. via ExternalTable)
Daten aufbereiten (z.B. Dubletten entfernen, plus Rückmeldung / Log)
Daten dann mit System-/Produktivdaten abgleichen und ggF. importieren.
Dabei gehst Du sehr wahrscheinlich Satz für Satz durch die neuen Daten und schaust wo und wie Du sie unterbringst. (Wiederum mit Rückmeldung bzw. Log für automatisierte Prozesse)

Konvertierung:
Es ist stark anzunehmen, dass Deine CSV Daten im Klartext dort stehen und Integer bspw nicht 2 oder 4 Byte binär codiert sind.
Also Integer auch als Varchar einlesen mit Längenangabe entsprechend dem CSV.
P.S.: Wenn Du aus der DB dann auf die "integer" Daten zugreifst, musst Du konvertieren.
Also beim Insert in die Zieltabelle z.B..

blutigerAnfänger 8. Sep 2014 16:25

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:

Zitat von jobo (Beitrag 1271517)
Ich möchte noch ergänzen, dass das Bedürfnis nach einer eindeutigen ID natürlich legitim ist. Was und wie Du aber auch immer importierst, die zu importierenden Daten sollten über solch ein eindeutiges Merkmal bereits verfügen, notfalls über mehrere Felder und idealer Weise auch gegenüber den bereits importierten Daten. Ansonsten holst Du Dir die Leichen reihenweise in den Keller.

Schau Dir mal Literatur zum Thema ETL an. Ganz grob:
Daten temporär in der DB bereitstellen (z.B. via ExternalTable)
Daten aufbereiten (z.B. Dubletten entfernen, plus Rückmeldung / Log)
Daten dann mit System-/Produktivdaten abgleichen und ggF. importieren.
Dabei gehst Du sehr wahrscheinlich Satz für Satz durch die neuen Daten und schaust wo und wie Du sie unterbringst. (Wiederum mit Rückmeldung bzw. Log für automatisierte Prozesse)

Konvertierung:
Es ist stark anzunehmen, dass Deine CSV Daten im Klartext dort stehen und Integer bspw nicht 2 oder 4 Byte binär codiert sind.
Also Integer auch als Varchar einlesen mit Längenangabe entsprechend dem CSV.
P.S.: Wenn Du aus der DB dann auf die "integer" Daten zugreifst, musst Du konvertieren.
Also beim Insert in die Zieltabelle z.B..

Zum 1ten Absatz:
Also am besten mit einem 2ten Integer Feld (in dem bereits die Autoinc enthalten ist)??

zum 2ten Absatz:
Nenn mir doch mal eine deutschsprachige Literatur zum Thema ETL (externalTabelle?), welche möglichst einfach gehalten ist. Vielleicht gibt's da noch etwas was ich bei meiner Recherche übersehen habe.

zum 3tenAbsatz (Konvertierung):
Anbei zwei Screenshots, beide zeigen die Ergebnisse der external Tabelle aus IBexpert personnel.
Der eine Screenshot zeigt das Importergebnis von CHAR, der andere das Importergebnis von VARCHAR an beide mit Länge 10.

mkinzler 8. Sep 2014 16:27

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Und wie sieht die Datei aus?

jobo 8. Sep 2014 16:40

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von blutigerAnfänger (Beitrag 1271654)
Zum 1ten Absatz:
Also am besten mit einem 2ten Integer Feld (in dem bereits die Autoinc enthalten ist)??

zum 2ten Absatz:
Nenn mir doch mal eine deutschsprachige Literatur zum Thema ETL (externalTabelle?), welche möglichst einfach gehalten ist. Vielleicht gibt's da noch etwas was ich bei meiner Recherche übersehen habe.

zum 3tenAbsatz (Konvertierung):
Anbei zwei Screenshots, beide zeigen die Ergebnisse der external Tabelle aus IBexpert personnel.
Der eine Screenshot zeigt das Importergebnis von CHAR, der andere das Importergebnis von VARCHAR an beide mit Länge 10.

Ich weiß nicht, warum es ein 2tes Integerfeld sein muss. Was am besten ist, weiß ich auch nicht, es kommt auf Deine Daten an. Wenn die eindeutige Merkmale enthalten, kannst Du diese Spalten für den eindeutigen Zugriff nutzen

ETL beschreibt den Vorgang ExtractLoadTransform oft verwendet in Datawarehouse Systemen:
http://de.wikipedia.org/wiki/ETL-Prozess

Sieht so aus, als ob Deine Längenangaben nicht zur CSV Datei passen. Feld-Trennzeichen wird mitgelesen oder so.

blutigerAnfänger 8. Sep 2014 16:52

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von mkinzler (Beitrag 1271655)
Und wie sieht die Datei aus?

Zitat:

Zitat von jobo (Beitrag 1271657)
Ich weiß nicht, warum es ein 2tes Integerfeld sein muss. Was am besten ist, weiß ich auch nicht, es kommt auf Deine Daten an. Wenn die eindeutige Merkmale enthalten, kannst Du diese Spalten für den eindeutigen Zugriff nutzen

ETL beschreibt den Vorgang ExtractLoadTransform oft verwendet in Datawarehouse Systemen:
http://de.wikipedia.org/wiki/ETL-Prozess

Sieht so aus, als ob Deine Längenangaben nicht zur CSV Datei passen. Feld-Trennzeichen wird mitgelesen oder so.

Meine Testtabelle mit fixer Länge(wie external Table vorschreibt): Das erste Feld Integer mit 10 Zeichen Länge, Das zweite Feld STring bzw.Char(nach Vorschrift) mit Länge 50, Das dritte Feld String bzw. Char mit 250er Länge.

Dejan Vu 8. Sep 2014 17:01

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
CSV? Ich lese immer CSV... Kann Firebird das denn? So wie ich das verstanden habe, muss die Textdatei feste Breiten haben... Oder geht das etwa? :gruebel:

jobo 8. Sep 2014 17:20

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Zitat von Dejan Vu (Beitrag 1271661)
CSV? Ich lese immer CSV... Kann Firebird das denn? So wie ich das verstanden habe, muss die Textdatei feste Breiten haben... Oder geht das etwa? :gruebel:

Ich glaube nur feste Breite. CSV ist scheinbar der schlampige Standardbegriff für alles was Daten lesbar in Textform enthält.

Mein Hinweis mit den micht berücksichtigten Spaltentrennzeichen war dementsprechend daneben.

Aber die Datei ist ja offenbar fixed length. Sollte also in Ordnung sein.
Eine Zeile 310 Bytes, mit Umbrauch 312.

Jumpy 9. Sep 2014 08:01

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Irgendwie sieht das so aus, das der Import eine Datei ohne Zeilenumbrüche erwartet.
Mach doch alle Zeilenumbrüche aus der Datei raus oder mach ein 4tes Feld Länge 2, dass die Zeielnumbruchzeichen aufnimmt.

blutigerAnfänger 9. Sep 2014 11:49

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Ich hab's geschafft. Zwei Fehler:

1. Fehler: Im Vorbereitungsprogramm, welches die fixe Länge erzeugt, hat sich beim Kopieren ein falscher Index eingeschlichen. Deswegen war die External Tabelle so ziemlich durcheinandergeraten. Korrigiert.
Externe Tabelle funktioniert nachwievor nur mit Char (kein Varchar, kein Integer o.A.)

2.Fehler Die FirebirdZieltabelle hatte wie beschrieben 4 Felder, (Checkbox Integer, Name Varchar, Bezeichnung Varchar, und ID Integer. Das ID Integer Feld gelöscht und der Import läuft fehlerfrei.

Danke an Alle.

mkinzler 9. Sep 2014 17:15

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Zitat:

Externe Tabelle funktioniert nachwievor nur mit Char (kein Varchar, kein Integer o.A.)
Ja, aber du kannst es ja beim Kopieren von der externen Tabelle in die Zieltabelle konvertieren (casten)

SQL-Code:
insert into <Tabelle>(...) select cast( checkbox as Integer), ... from dat_ext

Sir Rufo 9. Sep 2014 17:47

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Irgendwie klingt es ja auch logisch, dass bei einer festen Breite auch der Datentyp eine feste Breite hat ;)

blutigerAnfänger 12. Sep 2014 07:31

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Das Problem mit dem ID Feld hat sich auch erledigt.
Das nachträgliche Einfügen der ID Tabelle funktioniert zwar, aber der Trigger und der Generator lassen sich nicht zum laufen bringen(Trigger nicht einmal erzeugen).
Das Problem läßt sich durch das Einfügen eines zusätzlichen Feldes (ID) im Vorbereitungsprogramm umgehen. Fügt zwar ein "statisches" ID Feld ein, ist aber für den Zweck völlig egal.

Dejan Vu 12. Sep 2014 11:19

AW: Einfügen über externalTabelle funktioniert nicht richtig
 
Wieso willst Du in einer externen Tabelle denn überhaupt so eine ID haben?

Nochmal: Die 'EXTERNAL TABLE' Funktionalität ist dazu da, um auf externe Dateien zugreifen zu können. Du sollst die tunlichst in eine andere Tabelle überführen, wo Du dann deine Trigger, AutoInc-Spalten, Integer, Numeric, foobars und sonst was für Datentypen hast.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:14 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