"PHP how-to" CSV-Datei in MySQL importieren - Johannes Schwichtenberg

johannesschwichtenberg.de

Verarbeitung einer CSV-Datei und Import in eine MySQL-Datenbank

PHP how-to

Im Artikel Datenbank-Import und MySQL-Optimierung gehe ich bewusst auf die Verarbeitung einer CSV-Datei als Datenquelle nicht ein, einige Grundlagen sollen an dieser Stelle vermittelt werden:
Wie können also Daten aus einer Datei in eine Tabelle importiert werden?

Zuerst muss natürlich geklärt werden, in welchem Schema die Daten in der Datei geordnet sind, hierbei sind folgende Varianten geläufig (CSV steht übersetzt für „kommaseparierte Felder“):

  • Ein Datensatz steht in einer Zeile
  • Felder oder „Spalten“ sind per Komma getrennt,
  • per Semikolon oder
  • per Tabulator

Nehmen wir folgende CSV-Datei als Beispiel:

123;"Mein test"
435;"Weiterer
test"

Zugriff auf die CSV-Datei

Der Code für den Zugriff könnte folgendermaßen aussehen:

<?php
$fp = fopen("test1.csv", "r");
$zeilen = array();

while( !feof($fp) ) {
    $zeilen[] = fgetcsv  ( $fp  , 4096 , ";" , "\"" );
}
fclose($fp);
?>

Kurz ein paar Erläuterungen, die man ebenfalls auf php.net nachlesen kann, häufig helfen dort auch die Benutzter-Kommentare.
PHP stellt mit fgetcsv(..) eine Funktion bereit, die eine Datei-Zeile in die einzelnen Felder zerlegt und als Array zurückgibt. Dieser Funktion muss der Zeiger (hier $fp) auf die geöffnete Datei übergeben werden, die zu lesende Zeilenlänge, das Trennzeichen (Standardwert ist Komma) und ein Zeichen mit dem die Felder eingeschlossen sind (die letzten beiden Parameter sind optional). Praktisch an dieser Funktion ist, dass Zeilenumbrüche, wie in diesem Beispiel, berücksichtigt werden und nicht zur Zerstörung der Datensätze führen. Die Funktion muss in einer Schleife aufgerufen werden, damit alle Datei-Zeilen abgearbeitet werden.

Anschließend kann man die Daten weiterverarbeiten. In diesem Beispiel wäre zu Testzwecken eine Ausgabe mittels print_r($zeilen) denkbar.
Es ist natürlich auch möglich für jede Zeile – also pro Schleifendurchlauf – eine Verarbeitung vorzunehmen, abhängig davon, was erledigt werden soll.

Import der Daten in die MySQL Datenbank-Tabelle

Als nächstes kann man sich Gedanken über das Einfügen der Daten in die Datenbank-Tabelle machen.
Nehmen wir an, es existiert eine simple Tabelle mit zwei Spalten, die mit dem Inhalt der genannten CSV-Datei gefüllt werden sollen.

<?php 
//Datenbankverbindung besteht
$fp = fopen("test1.csv", "r");

define("CSV_KDNR", 0);
define("CSV_NAME", 1);

$query = "INSERT INTO test1 VALUES ";

while( !feof($fp) ) {
    $zeile = fgetcsv  ( $fp  , 4096 , ";"  );
    $query .= " (".$zeile[CSV_KDNR].", '".$zeile[CSV_NAME]."' ),";
}

$query = substr($query, 0, -1);
mysql_unbuffered_query($query);
fclose($fp);
?>

Zur Erläuterung: Per define habe ich einige sogenannte Enumeratoren angelegt – da diese in PHP nicht wie in anderen Sprachen standardmäßig implementiert sind, habe ich einfach Konstante verwendet. Der Sinn ist, dass man einen „sprechenden Schlüssel“ enthält und falls sich der Aufbau der CSV-Datei einmal verändert, muss nur an einer Stelle die Feld-Index-Zuordnung korrigiert werden.
Entsprechend meines Artikels zur MySQL-Optimierung fasse ich die INSERT-Befehle zusammen und hänge diese bei jedem Schleifendurchlauf an die bisher bestehenden. Dem Einschleusen von schadhaftem Code aus der CSV-Datei muss je nach Datei-Ursprung/Inhalt durch Prüfung der Datentypen oder durch Escapen (z.B. mysql_real_escape_string()) an dieser Stelle vorgebeugt werden. Anschließend muss das letzte automatisch angehängte Komma abgeschnitten werden und das Statement kann ausgeführt werden.

Zu beachten sind eventuelle Konflikte aufgrund des Tabellen-Aufbaus. Wenn Primärschlüssel existieren, die in einem weiteren Datensatz nun noch einmal importiert werden sollen, gibt es Fehlermeldungen von MySQL und der Befehl wird nicht ausgeführt. Per Aufruf von echo mysql_error() kann man die Fehlerursache zu Debug-Zwecken schnell herausfinden.

 

Hinweis: Sämtliche Informationen ohne Garantie und Anspruch auf Vollständigkeit, jedoch nach bestem Wissen des Autors zum Zeitpunkt der Erstellung.