Problem bei CSV-Import (zeit überschritten)
Maria
- php
Hallo,
ich bin gerade dabei eine Datei zu schreiben um komfortabel CSV-Dateien von Partnerprogrammen in eine MySQL-DB zu importieren:
9: $import = file("$ok.csv");
10:
11: foreach($import as $fh)
12: {
13: $handy = explode(";", $fh);
14:
15: $daten= "INSERT INTO affili_handy (id, artikelnr, titel, beschreibung, preis, bild, link, pcid, pcname, anbieter) VALUES ('','$handy[0]','$handy[1]','$handy[2]','$handy[3]','$handy[4]','$handy[5]','$handy[6]','$handy[7]','a$ok')";
16: }
Die Variable $ok wird weiter oben festgelegt und steigt immer um 1 bis zum Zielwert der in der Configdatei angegeben ist (ist eine schleife um mehrere CSVs nacheinander zu importieren)
Nun bekomm ich aber immer folgenden Fehler:
[b]Fatal error: Maximum execution time of 30 seconds exceeded in www/bonus/test/csvcron.php on line 9
[/b]
Die zeilen nummer ändert sich auch mal auf 13 oder 15, je nachdem wie der Server grad mag.
Wo liegt da das Problem? Ich komm da einfach nicht weiter.
Danke im vorraus für eure Hilfe
achja, und dann hab ich da noch ein Problem mit
$handy = fgetcsv($fh,1048576,';');
das sollte laut einer Anleitung vor Zeile 13 stehen, aber da gibts auch immer nur Fehlermeldungen:
Warning: fgetcsv(): supplied argument is not a valid stream resource
Hallo,
ich kann dir leider nicht helfen, hab aber eine kleine Zwischenfrage an alle.
15: $daten= "INSERT (...) VALUES ('',(...))";
Die zwei einfachen Anführungszeichen stehen für den Inhalt des id-Feldes.
Ich geh mal davon aus, dass der Wert per auto_increament eingetragen wird.
Wär es dann nicht semantisch korrekt "NULL" anstatt der beiden einfachen Anführungszeichen zu schreiben?
Oder macht das keinen Unterschied?
Die Variable $ok wird weiter oben festgelegt und steigt immer um 1 bis zum Zielwert der in der Configdatei angegeben ist (ist eine schleife um mehrere CSVs nacheinander zu importieren)
Versuch mal übergabe der Variable mittels echo auszugeben.
Eventuell enthält $ok nicht das was du willst.
Die zeilen nummer ändert sich auch mal auf 13 oder 15, je nachdem wie der Server grad mag.
Das halte ich für sehr eigenartig.
Grüße, Matze
echo $begrüßung;
15: $daten= "INSERT (...) VALUES ('',(...))";
Die zwei einfachen Anführungszeichen stehen für den Inhalt des id-Feldes.
Ich geh mal davon aus, dass der Wert per auto_increament eingetragen wird.
Wär es dann nicht semantisch korrekt "NULL" anstatt der beiden einfachen Anführungszeichen zu schreiben?
Das MySQL-Handbuch schreibt auf der Seite zu den Numeric Types, dass für eine auto_increment-Spalte NULL bevorzugt ist, ansonsten aber auch 0 verwendet werden kann. Ein Leerstring wird durch die automatische Typumwandlung zu 0. Es ist aber auch möglich, diese Spalte komplett wegzulassen, also sowohl in der Auflistung der Felder als auch bei den Werten.
echo "$verabschiedung $name";
Hallo,
Wär es dann nicht semantisch korrekt "NULL" anstatt der beiden einfachen Anführungszeichen zu schreiben?
Also ja?
Es ist aber auch möglich, diese Spalte komplett wegzulassen, also sowohl in der Auflistung der Felder als auch bei den Werten.
Dachte ich auch, aber bei einem meiner letzten Projekte wollte der Server unbedingt eine Angabe. Kann man sicher irgendwo einstellen.
Grüße, Matze
echo $begrüßung;
Wär es dann nicht semantisch korrekt "NULL" anstatt der beiden einfachen Anführungszeichen zu schreiben?
Also ja?
Der Satz im Handbuch lautet "When you insert a value of NULL (recommended) or 0 into an indexed AUTO_INCREMENT column, the column is set to the next sequence value." Ich übernehme nicht die Rolle eines Handbuchaussagenbestätigers. Du musst da schon selbst draus schlussfolgern, was immer du willst. :-)
Es ist aber auch möglich, diese Spalte komplett wegzulassen, also sowohl in der Auflistung der Felder als auch bei den Werten.
Dachte ich auch, aber bei einem meiner letzten Projekte wollte der Server unbedingt eine Angabe. Kann man sicher irgendwo einstellen.
Das ist mir nicht bekannt. Ich nehme an, du hast da was verkehrt gemacht.
echo "$verabschiedung $name";
echo $begrüßung;
ich bin gerade dabei eine Datei zu schreiben um komfortabel CSV-Dateien von Partnerprogrammen in eine MySQL-DB zu importieren:
Du willst also LOAD DATA INFILE, vermutlich, weil du das Statement nicht kennst, ebensowenig wie das Kommandozeilenprogramm mysqlimport, oder die die Voraussetzugen für den Einsatz dieser Alternativen fehlen.
Nun bekomm ich aber immer folgenden Fehler:
[b]Fatal error: Maximum execution time of 30 seconds exceeded in www/bonus/test/csvcron.php on line 9
Du versuchst zu viel auf einen Schlag ablaufen zu lassen, bzw. versuchst dies in einer ungünstigen Umgebung. Wenn du das Script von der Kommandozeile aus startest ist per Default keine Laufzeitbegrenzung aktiv. Innerhalb eines Webservers sorgt diese Begrenzung dafür, dass hängengebliebene Scripte entsorgt werden. Wenn du auf die Kommandozeile wechseln kannst, solltest du das tun. Ansonsten könntest du probieren, max_execution_time hochzusetzen. Innerhalb des Scripts mit ini_set(), oder auch außerhalb. Sollten dir (beim Provider) keine der Möglichkeiten zur Verfügung stehen, wird dir nichts anderes übrigbleiben, als mehrere Durchläufe mit kleineren Häppchen zu starten.
echo "$verabschiedung $name";
Du willst also LOAD DATA INFILE, vermutlich, weil du das Statement nicht kennst, ebensowenig wie das Kommandozeilenprogramm mysqlimport, oder die die Voraussetzugen für den Einsatz dieser Alternativen fehlen.
Du versuchst zu viel auf einen Schlag ablaufen zu lassen, bzw. versuchst dies in einer ungünstigen Umgebung. Wenn du das Script von der Kommandozeile aus startest ist per Default keine Laufzeitbegrenzung aktiv. Innerhalb eines Webservers sorgt diese Begrenzung dafür, dass hängengebliebene Scripte entsorgt werden. Wenn du auf die Kommandozeile wechseln kannst, solltest du das tun. Ansonsten könntest du probieren, max_execution_time hochzusetzen. Innerhalb des Scripts mit ini_set(), oder auch außerhalb. Sollten dir (beim Provider) keine der Möglichkeiten zur Verfügung stehen, wird dir nichts anderes übrigbleiben, als mehrere Durchläufe mit kleineren Häppchen zu starten.
Ok, aber wie mach ich das? Wie kann ich z.B. nur die zeilen 2-10 und dann 11-20 auslesen und in die DB eintragen?
Hatte jetzt auch mal folgendes ausprobiert:
$ok = '1';
while($ok < $wieviel)
{
$row = 1;
$handle = fopen ("$ok.csv","r");
while ($handy = fgetcsv ($handle, 1000, ";"))
{
$insert_csv = "INSERT INTO affili_handy ";
$insert_csv .= "(id, artikelnr, titel, beschreibung, preis, bild, link, pcid, pcname, anbieter) ";
$insert_csv .= "VALUES ";
$insert_csv .= "('','$handy[0]','$handy[1]','$handy[2]','$handy[3]','$handy[4]','$handy[5]','$handy[6]','$handy[7]','a$ok')";
mysql_query($insert_csv);
}
fclose ($handle);
}
$ok++;
Hatte den Code im netz gefunden und nur ein wenig angepasst um zu sehen wie es da abläuft, diesmal wird zwar etwas in die DB eingetragen, aber MASSENHAFT. 3 CSV-Dateien sollten importiert werden testweise, das wären ~45 Einträge in der DB, aber das Script hört da ganr nicht mehr auf zu laden und nachdem ich 10 Minuten später in die DB schau sind da über 600.000 Einträge in der Datenbank!
echo $begrüßung;
Ok, aber wie mach ich das? Wie kann ich z.B. nur die zeilen 2-10 und dann 11-20 auslesen und in die DB eintragen?
Indem du mitzählst und die ungewünschten Zeilen ignorierst. Aber das brauchst du nicht, dein Fehler steckt woanders.
Hatte den Code im netz gefunden und nur ein wenig angepasst um zu sehen wie es da abläuft, diesmal wird zwar etwas in die DB eingetragen, aber MASSENHAFT. 3 CSV-Dateien sollten importiert werden testweise, das wären ~45 Einträge in der DB, aber das Script hört da ganr nicht mehr auf zu laden und nachdem ich 10 Minuten später in die DB schau sind da über 600.000 Einträge in der Datenbank!
Du hast eine Endlos-Schleife programmiert. Wenn du dir zum Test innerhalb der Schleife while($ok < $wieviel) den Wert von $ok ausgeben lässt, wirst du feststellen, dass sich dieser nicht erhöht. Reicht dir dieser Hinweis schon?
Ich bin mir sicher, wenn du mehr Augenmerk auf die Einrückung deines Codes, besonders von Schleifeninhalten, legtest, würdest du weniger solcher Fehler erzeugen bzw. sie schneller entdecken.
echo "$verabschiedung $name";
Du hast eine Endlos-Schleife programmiert. Wenn du dir zum Test innerhalb der Schleife while($ok < $wieviel) den Wert von $ok ausgeben lässt, wirst du feststellen, dass sich dieser nicht erhöht. Reicht dir dieser Hinweis schon?
Ich bin mir sicher, wenn du mehr Augenmerk auf die Einrückung deines Codes, besonders von Schleifeninhalten, legtest, würdest du weniger solcher Fehler erzeugen bzw. sie schneller entdecken.
echo "$verabschiedung $name";
Oh man bin ich dumm ;)
Jetzt hab ich nur noch ein problem, und zwar steht in jeder CSV ganz am anfang eine Zeile mit Spaltennamen, diese sollen aber nicht mit in die Datenbank importiert werden sondern vorher aussortiert.
Gibt es einen Befehl um erst ab Zeile 2 beim auslesen bzw. bearbeiten anzufangen?
echo $begrüßung;
Jetzt hab ich nur noch ein problem, und zwar steht in jeder CSV ganz am anfang eine Zeile mit Spaltennamen, diese sollen aber nicht mit in die Datenbank importiert werden sondern vorher aussortiert.
Gibt es einen Befehl um erst ab Zeile 2 beim auslesen bzw. bearbeiten anzufangen?
Du könntest, bevor du in die Ausleseschleife nach dem fopen() eintrittst, eine Zeile lesen und nicht weiter bearbeiten.
echo "$verabschiedung $name";
Hallo,
Grüße,
Nun bekomm ich aber immer folgenden Fehler:
[b]Fatal error: Maximum execution time of 30 seconds exceeded in www/bonus/test/csvcron.php on line 9
[/b]
Schau mal hier [Link:http://de3.php.net/manual/de/ref.info.php#ini.max-execution-time]
Das heisst im Klartext, die Verarbeitung deines Scriptes dauert zu lange. Lösungsansatz wäre erstmal jede .csv einzeln abzuhandeln und nicht alle in einem Rutsch.
Hoffe konnte etwas weiterhelfen.
grüße
Hallo,
Grüße,
Nun bekomm ich aber immer folgenden Fehler:
[b]Fatal error: Maximum execution time of 30 seconds exceeded in www/bonus/test/csvcron.php on line 9
[/b]Schau mal hier [Link:http://de3.php.net/manual/de/ref.info.php#ini.max-execution-time]
Das heisst im Klartext, die Verarbeitung deines Scriptes dauert zu lange. Lösungsansatz wäre erstmal jede .csv einzeln abzuhandeln und nicht alle in einem Rutsch.
Hoffe konnte etwas weiterhelfen.
grüße
Es wird ja jede einzeln nacheinander abgefragt und eingetragen, aber er das script fängt nichtmal an damit, in die DB wird gar nichts eingetragen
Hallo Maria,
dann würde ich vorschlagen, du schaust dir mal [Link:http://forum.de.selfhtml.org/?t=158939&m=1033899@title=dedlfix's_Anwort] an.
Es wird ja jede einzeln nacheinander abgefragt und eingetragen, aber er das script fängt nichtmal an damit, in die DB wird gar nichts eingetragen
einen sonnigen Freitag noch :)
echo $begrüßung;
Es wird ja jede einzeln nacheinander abgefragt und eingetragen, aber er das script fängt nichtmal an damit, in die DB wird gar nichts eingetragen
Ja, das kann ja auch nicht mit dem Stück Code, das du gepostet hast. Denn da ist keine Anweisung drin, der sich mit dem MySQL-Server unterhält.
echo "$verabschiedung $name";
echo $begrüßung;
Ich hab noch was wichtiges vergessen.
ich bin gerade dabei eine Datei zu schreiben um komfortabel CSV-Dateien von Partnerprogrammen in eine MySQL-DB zu importieren:
9: $import = file("$ok.csv");
11: foreach($import as $fh)
13: $handy = explode(";", $fh);
Diese Vorgehensweise berücksichtigt nicht die Regeln für CSV-Dateien in Hinsicht auf Begrenzungszeichen. Was ist, wenn ein feldertrennendes ; innerhalb eines Feldes steht, das korrekt mit Quotierungzeichen eingerahmt ist? Dann teilst du das eine Datum in zwei "Datümer" auf und es verschieben sich alle nachfolgenden Spalten. Mal abgesehen davon, dass die Quotierungszeichen nicht berücksichtigt werden.
Die Funktion fgetcsv() ist speziell für CSV-Dateien gemacht. Sie berücksichtigt alle Regeln. Allerdings arbeitet sie nicht mit dem Array zusammen, das bei file() entsteht. Du müsstest sie und weitere File-Funktionen schon so anwenden, wie es das Beispiel auf der Handbuchseite macht. Dann tritt auch dein Fehler nicht auf.
15: $daten= "INSERT INTO affili_handy (id, artikelnr, titel, beschreibung, preis, bild, link, pcid, pcname, anbieter) VALUES ('','$handy[0]','$handy[1]','$handy[2]','$handy[3]','$handy[4]','$handy[5]','$handy[6]','$handy[7]','a$ok')";
Auch du ignorierst die Möglichkeit, dass das Zeichen ' innerhalb der Daten vorkommen kann (z.B. in Namen wie O'Brien). Dieses und andere Zeichen müssen besonders notiert werden, auch Escaping genannt. PHP kennt dafür für MySQL die Funktion mysql_real_escape_string().
Oder als Lehrsatz formuliert: Wann immer du Daten in einen anderen Kontext bringst, musst du sie kontextspezifisch behandeln.
echo "$verabschiedung $name";