dgr243 Geschrieben 29. Juli 2004 Teilen Geschrieben 29. Juli 2004 Moin zusammen. Folgende Aufgabenstellung: Nimm eine CSV Datei der Form: "wert1;wert2;[..];wert10" und packe diese per DBI und DBD::ODBC in eine bestehende Access Tabelle. Mein Ansatz ist bis jetzt folgender: use DBI; # Declare variables my $dsn = Access; #DSN im ODBC my $db = 'c:/repo'; #Ort der CSV datei my $separator='\\;' ; #Spaltentrenner ";" my $filename = 'mappe1.csv'; # Makes a Datebase Handler my $dbh = DBI->connect("DBI:ODBC:$dsn") or die DBI::errstr; #ODBC Access my $dbh2 = DBI->connect("DBI:CSV:f_dir=$db;csv_sep_char=$separator") or die "öffnen: DBI::errstr"; #CSV Datei c:\repo\mappe1.csv $dbh2->{csv_tables}->{temps} = {'file' => $filename}; my $sth2 = $dbh2->prepare("select * from temps") or die "1: $dbh2->errstr"; $sth2->execute() or die "2: $dbh2->errstr"; while (my @row = $sth2->fetchrow_array()) { my $sth = $dbh->do("insert into temps values (@row)") or die "3: $dbh2->errstr"; } $dbh->disconnect(); $dbh2->disconnect(); Als Fehlermeldung erhalte ich: DBD::ODBC::db do failed: [Microsoft][ODBC Microsoft Access Driver] Syntaxfehler (fehlender Operator) in Abfrageausdruck '15.May.2003;10:00;23'. (SQL-42000)(DBD: Execute immediate failed err=-1) at c:\eigene dateien\perl\progs\odbc2.pl line 23. 3: DBI::db=HASH(0xb04fe54)->errstr at c:\eigene dateien\perl\progs\odbc2.pl line 23. Und irgendwo hab ich da jetzt nen kräftigen Block im Kopp wo ich net weiterkomm... Würde mich sehr freuen, wenn mir da wer nen Tip geben könnte. Alternativ nehme ich auch gerne Lösungsvorschläge, wie es komplett anders gehen könnte Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 29. Juli 2004 Teilen Geschrieben 29. Juli 2004 Lasse dir mal bitte die generierte SQL-Anweisung ausgeben. Denn da liegt der Hase begraben. Wieso gibts du bei dem Spaltentrenner "\\;" an? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 29. Juli 2004 Autor Teilen Geschrieben 29. Juli 2004 Lasse dir mal bitte die generierte SQL-Anweisung ausgeben. Denn da liegt der Hase begraben. Wieso gibts du bei dem Spaltentrenner "\\;" an? Ok die werte sind durch semikolon getrennt, nicht durch komma ... na gut, dass wird na klar schwer das als getrennte werte auszugeben wie trenne ich denn jetzt mal am besten die werte mit komma? bin relativer perl newbie, deswegen grad etwas ratlaos... Spaltentrenner "\\;" da ein einfach ";" sonst als trenner der argumente für dbd:csv gewertet werden würde. deshalb hab ich das mit dem "\\" entwertet, wie das vorgeschlagen wurde in der dbd:csv hilfe ... sollte das nicht richtig sein ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 29. Juli 2004 Teilen Geschrieben 29. Juli 2004 my @liste; my @eintrag; my $file = "dateiname"; open(CVSFILE,$file); while (<CVSFILE>) { @eintrag = split(/;/,$_); # hier den Eintrag in die Datenbank vornehmen } close(CVSFILE); [/PHP] Ich hoffe mal es klappt. Habe ewig nichts mehr mit Perl zu tun gehabt. [OT] Wieso nimmt man eigentlich unter Windows Perl um auf eine Access-DB zuzugreifen? :confused: [/OT] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 29. Juli 2004 Autor Teilen Geschrieben 29. Juli 2004 Hallo Enrico, ok die CSV Datei als Datei und nicht als SQL DB zu öffnen ist natürlich auch ein gangbarer weg Ich habe jetzt folgendes Perl Script und nun das Problem, dass die Datenbank meckert, dass sie mehrere Argumente erwartet aber nur eins bekommt: use DBI; use diagnostics; # Declare variables my $dsn = Access; #DSN im ODBC my @liste; my @eintrag; # Makes a Datebase Handler my $dbh = DBI->connect("DBI:ODBC:$dsn") or die DBI::errstr; #ODBC Access open(CVSFILE,"c:\\repo\\mappe1.csv") or die "Cannot open source file"; while (<CVSFILE>) { @eintrag = split(/;/,$_); my $sth = $dbh->prepare("insert into temps values (@eintrag)") or die $dbh->errstr; $sth->execute(); } $dbh->disconnect(); close(CVSFILE); Ich vermute, dass die Auflösung des SQL Statements nicht so funzt wie ich mir das denke.... @eintrag sollte an dieser Stelle zu einem String der form "Wert1,Wert2,Wert3,[..]" interpoliert werden, was so leider nicht geschieht .... Könnte ich nicht theoretisch nach dem Split folgende Zuweisungen treffen: #Hier nur die while Schleife nach dem Öffnen der Datei while (<CVSFILE>) { @eintrag = split(/;/,$_); my $wert1 = $eintrag[0]; my $wert2 = $eintrag[1]; my $statement = "$wert1 . , . $wert2" my $sth = $dbh->prepare("insert into temps values ($statement)") or die $dbh->errstr; $sth->execute(); } In dem Codeschnipsel will allerdings auch irgendwas noch nicht so wie ich das will ... [OT] [OT] Wieso nimmt man eigentlich unter Windows Perl um auf eine Access-DB zuzugreifen? :confused: [/OT] Ich sag nur gewachsene Strukturen .. die Access DB existiert schon länger und soll nicht ersetzt werden. Dennoch soll das ganze ins Web bzw. vorab mit CSV Dateien gefüttert werden... [/OT] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 29. Juli 2004 Teilen Geschrieben 29. Juli 2004 @eintrag = split(/;/,$_); my $value; my $sql = "insert into temps values "; while (($value = shift @eintrag)) { $sql .= "'$value'"; if ($eintrag > 0) { $sql .= ", "; } } my $sth = $dbh->prepare($sql) or die $dbh->errstr; $sth->execute(); [/PHP] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 Super passte fastkomplett.. fehlten nur die Klammern um die einzelnen Werte der SQL Anweisung, aber die hab ich dann ma hinzu gebastelt. Vielen Dank soweit! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 Arghs .. nu hab ich mir da aber nen anderes Problem eingehandelt: Die zusammengebastelte SQL Anweisung sieht dann so aus: $sql = "insert into temps values ('String','String2','x,y',[...]) 'x,y' geht natürlich nicht, weil das insert into Statement bei Zahlen die in eine DB geschubst werden Dezimalzahlen in der Form "x.y" also mit nem Punkt als dezimalzeichen und ohne Anführungszeichen erwartet. Nu müsste ich entweder die Schleife ändern oder hinterher die fertige SQL Anweisung.... was ist leichter und wie gehts? Mann mann und das am Freitag .. da kann ich doch eh nicht denken ... Der Vollständigkeit halber: CSV Datei beinhaltet folgendes Format: "Datum;Uhrzeit;Dezimal1;Dezimal2;Dezimal3;Dezimal4;Dezimal5;Dezimal6;Dezimal7;Dezimal8" Hierbei sind alle " und ; genau wie oben geschrieben in der CSV Datei enthalten. Die Tabelle in die hinein geschubst wird erwartet - Datum als String (also in ' ') - Uhrzeit als Stzring (also in ' ') - Dezimal[1-8] als Double (also mit . und ohne ' ') Und hier das Script wie es derzeit ausschaut: use DBI; use diagnostics; # Declare variables my $dsn = Access; #DSN im ODBC my @liste; my @eintrag; my $value; my $sql; my $sql2; # Makes a Datebase Handler my $dbh = DBI->connect("DBI:ODBC:$dsn") or die DBI::errstr; #ODBC Access open(CVSFILE,"c:\\repo\\mappe1.csv") or die "Cannot open source file"; while(<CVSFILE>) { @eintrag = split(/;/,$_); my $value; my $sql = ""; while (($value = shift @eintrag)) { $sql .= "'$value'"; if ($eintrag > 0) { $sql .= ", "; } } $sql .= "insert into temps values (" .$sql . ")"; print "\nSQL: $sql \n"; my $sth = $dbh->do($sql) or die $dbh->errstr; } $dbh->disconnect(); close(CVSFILE); Weiss noch wer Rat ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 30. Juli 2004 Teilen Geschrieben 30. Juli 2004 Machen wir das Ganze ebend etwas komplizierter while(<CVSFILE>) { @eintrag = split(/;/,$_); my $value; my $sql = ""; my $pos = 0; while (($value = shift @eintrag)) { switch (++$pos) { case 1 {$sql .= "'$value'";} case 2 {$sql .= "'$value'";} else {$value =~ s/,/./; $sql .= $value} } if ($eintrag > 0) { $sql .= ", "; } } $sql = "insert into temps values (" .$sql . ")"; print "\nSQL: $sql \n"; my $sth = $dbh->do($sql) or die $dbh->errstr; } [/PHP] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 Will leider nicht .. bin auch der meinung, dass perl "case" nicht kennt, oder? use DBI; # Declare variables my $dsn = Access; #DSN im ODBC my @liste; my @eintrag; my $wert; my $sql; my $sql2; # Makes a Datebase Handler my $dbh = DBI->connect("DBI:ODBC:$dsn") or die DBI::errstr; #ODBC Access open(CVSFILE,"c:\\repo\\mappe1.csv") or die "Cannot open source file"; while(<CVSFILE>) { @eintrag = split(/;/,$_); my $wert; my $sql = ""; my $pos = 0; while (($wert = shift @eintrag)) { switch (++$pos) { case 1 {$sql .= "'$wert'";} case 2 {$sql .= "'$wert'";} else {$wert =~ s/,/./;$sql .= $wert;} } if ($eintrag > 0) { $sql .= ", "; } } $sql = "insert into temps values (" .$sql . ")"; print "\nSQL: $sql \n"; sleep(3); #my $sth = $dbh->do($sql) or die $dbh->errstr; } $dbh->disconnect(); close(CVSFILE); Fehlermeldung: C:\Perl\bin>perl "c:\eigene dateien\perl\progs\odbc2.pl" Number found where operator expected at c:\eigene dateien\perl\progs\odbc2.pl line 25, near "case 1" (Do you need to predeclare case?) Number found where operator expected at c:\eigene dateien\perl\progs\odbc2.pl line 26, near "case 2" (Do you need to predeclare case?) syntax error at c:\eigene dateien\perl\progs\odbc2.pl line 24, near ") {" syntax error at c:\eigene dateien\perl\progs\odbc2.pl line 26, near "case 2" syntax error at c:\eigene dateien\perl\progs\odbc2.pl line 27, near "else" syntax error at c:\eigene dateien\perl\progs\odbc2.pl line 27, near ";}" Execution of c:\eigene dateien\perl\progs\odbc2.pl aborted due to compilation errors. Sorry, aber ich hab echt n Knoten im Kopf im Moment... aber vielen Dank für deine Hilfe! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 30. Juli 2004 Teilen Geschrieben 30. Juli 2004 da fehlte noch : use Switch; Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 da fehlte noch : use Switch; *vor kopf klatsch* Ja nee is klar .. ich seppel ... Allerdings kennt er das Modul switch nicht ... und der ppm von activestate gibt das auch net her .. du hast da nicht zufällig ne quelle für? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 Ich hab sjetzt entwas anders gelöst .. ohne switch ... Alelrdings hab ich nun 1 neues und ein alter -bishe rnicht entdecktes- problem: 1. An der eingelesenen Zeile aus der CSV Datei hängt noch ein Newline (\n)dran, dass noch raus muss 2. Auch zahlen haben nun ihre ' ' .... use DBI; # Declare variables my $dsn = Access; #DSN im ODBC my @eintrag; my $wert; my $sql; # Makes a Datebase Handler my $dbh = DBI->connect("DBI:ODBC:$dsn") or die DBI::errstr; #ODBC Access open(CVSFILE,"c:\\repo\\mappe1.csv") or die "Cannot open source file"; while(<CVSFILE>) { @eintrag = split(/;/,$_); #hier müsste vom letzten element des arrays (letzter wert) das newline \n entfernt werden mit chop... #wie kriege ich raus welches das letzte element ist? $sql = ""; while (($wert = shift @eintrag)) { $wert =~ s/,/./; $sql .= "'". $wert . "',"; #hiernach haben leider auch zahlen ein '' ..... wie vermeiden? } chop($sql); #Entfernen des letzten , $sql = "insert into temps werts (" .$sql . ")"; print "\nSQL: $sql \n"; my $sth = $dbh->do($sql) or die $dbh->errstr; } $dbh->disconnect(); close(CVSFILE); Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 30. Juli 2004 Teilen Geschrieben 30. Juli 2004 Verdammt noch mal! Scheint es erst seit Perl 5.8 zu geben. Hatte das Beispiel genutzt: http://www.perldoc.com/perl5.8.0/lib/Switch.html. Muss man eben etwas umschreiben: while (($wert = shift @eintrag)) { $pos++; if ($pos == 1) { # case 1 $sql .= "'$wert'"; } else if ($pos == 2) { # case 2 $sql .= "'$wert'"; } else { $wert =~ s/,/./; $sql .= $wert; } # ... weiter wie gehabt [/PHP] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 Wird sofort getestet .. Das Problem mit dem abschliessenden NewLine beim letzten Element des Arrays hab ich auch gelöst.... Gibt ja die "index vom letzten element" variable $#var ... gar nicht dran gedacht .. dann noch n chop($var[$#var]) hinterher und gut ... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 30. Juli 2004 Autor Teilen Geschrieben 30. Juli 2004 So mit ein paar Änderungen wegen Syntaxfehlern habe ich folgenden (funktionierenden) code: use DBI; use diagnostics; # Declare variables my $dsn = Access; #DSN im ODBC my @liste; my @eintrag; my $wert; my $sql; my $sql2; # Makes a Datebase Handler my $dbh = DBI->connect("DBI:ODBC:$dsn") or die DBI::errstr; #ODBC Access open(CVSFILE,"c:\\repo\\mappe1.csv") or die "Cannot open source file"; while(<CVSFILE>) { @eintrag = split(/;/,$_); chop($eintrag[$#eintrag]); #Abschliessende Newline am letzten Array element entfernen $sql = ""; my $pos = 0; while (($wert = shift @eintrag)) { $pos++; #Je nach pos (=index des arrays +1) entscheiden ob als string oder zahl geschrieben werden soll $sql .= "'$wert'," if ($pos==1); #Pos 1 als String $sql .= "'$wert'," if ($pos==2); #Pos 2 als String $wert =~ s/,/./ if ($pos != 1 && $pos != 2); #Wenn nicht Pos 1 oder 2 komma durch punkt ersetzen $sql .= "$wert," if ($pos != 1 && $pos != 2); #Alle anderen Positionen als Zahl ohne '' print "\n Werte: $sql"; } chop($sql); $sql = "insert into temps values (" .$sql . ")"; print "\nSQL: $sql \n"; my $sth = $dbh->do($sql) or die $dbh->errstr; } $dbh->disconnect(); close(CVSFILE); Es folgen dann jetzt die Erweiterungen ... Beispielsweise muss ich noch dafür sorgen, dass die erste Zeile der CSV Datei, die die Spaltennamen erhält nicht genutzt wird, da es sonst zu ODBC Fehlern kommt (Datentypen passen nicht...) aber das soltle das kleinere Prob werden. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
etreu Geschrieben 30. Juli 2004 Teilen Geschrieben 30. Juli 2004 Es folgen dann jetzt die Erweiterungen ... Beispielsweise muss ich noch dafür sorgen, dass die erste Zeile der CSV Datei, die die Spaltennamen erhält nicht genutzt wird, da es sonst zu ODBC Fehlern kommt (Datentypen passen nicht...) aber das soltle das kleinere Prob werden. Das möchte ich aber auch meinen. Wenn es trotzdem nicht klappen will: Hier werden Sie geholfen! :bimei Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dgr243 Geschrieben 2. August 2004 Autor Teilen Geschrieben 2. August 2004 Das möchte ich aber auch meinen. Wenn es trotzdem nicht klappen will: Hier werden Sie geholfen! :bimei Joah hat alles geklappt. Nun hab ich eine Vorlage für die anderen knapp 50 csv Dateien die importiert werden sollen (und na klar alle ein etwas anderes Format haben ) naja wird scho schief gehen. Danke nochmal Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.