Dabei meinen es die Unternehmen meist nur "gut" und wandeln es von sich aus ins gewohnte deutsche Format um, damit die Sachbearbeiter schneller damit zurecht kommen.
Daher möchte ich hier einfach mal eine einfache Möglichkeit zeigen, den Inport zu realisieren.
Dafür nehmen wir uns ein Beispiel, im folgenden sei der Aufbau der CSV-Datei (;-getrennt) beschrieben:
Code :
1 2 3 | KundenNr ArtikelNr1 ArtikelNr2 Anzahl Preis Variante Datum Adresse PLZ Land
001 Firma-5678 9854543241 3 4,50 2 21.12.2011 StraßeA 12 01234 DE
002 Firma-234 9854424241 2 11,97 5 22.12.2011 StraßeB 4 12345 DE |
Sowas kennen sicher viele. Hier haben wir folgende Probleme:
- die Kopfzeile wollen wir nicht importieren, unser Aufbau in der MySQL Datenbank entspricht ja dieser.
- die Spalte ArtikelNr2 (z.B. interne ArtNr. vom Unternehmenspartner), sowie Variante interessiert uns nicht und wollen wir nicht mit importieren.
- unsere Haupt-Artikelnummer ist z.B. 5stellig und wird vorne mit Nullen aufgefüllt. Zudem gehört unser Firmennamen nicht zu unserer Artikelnummer. (Andere Unternehmen machen dies oft um die Nummern zu unterscheiden)
- der Preis ist im deutschen Format angegeben, doch um Fehler zu vermeiden speichern wir Preise als Integer, also in Cent ab.
- die PLZ muss auch 5stellig sein. (Gerade wenn hier der Sachbearbeiter die CSV-Datei mit Excel öffnet, etwas ändert und speichert sind führende Nullen weg.)
- das deutsche Datumsformat bringt uns in der Datenbank leider sehr wenig.
MySQL bietet eine sehr einfache und elegante Lösung, solche Dateien zu importieren mit der Anweisung:
Code sql:
1 2 3 | LOAD DATA INFILE '{$file}' INTO TABLE kundentabelle
FIELDS TERMINATED BY ';' ENCLOSED BY ' '
LINES TERMINATED BY '\n' |
kundentabelle beschreibt unsere Zieltabelle in der Datenbank.
Hierbei habe ich öfter mal das Problem gehabt, dass das Leerzeichen bei ENCLOSED BY ' ' nicht anerkannt wurde, ich weiß bis heute nicht warum.
Solltet ihr auch dieses Problem aus PHP heraus haben, löst es wie folgt:
PHP-Code:
$query_str = sprintf("LOAD DATA INFILE '{$file}' INTO TABLE kundentabelle
FIELDS TERMINATED BY ';' ENCLOSED BY '%c'
LINES TERMINATED BY '\n' ", 34);
Die Kopfzeile (1 Zeile) zu ignorieren ist sehr einfach, dazu fügen wir folgende SQL-Zeile hinzu:
Code sql:
1 | IGNORE 1 LINES |
Im folgenden zählen wir alle Spalten aus der Tabelle kundentabelle auf, die aus der CSV-Datei zu ignorierenden Spalten bezeichnen wir mit @dummy
Code sql:
1 | (KundenNr, ArtikelNr1, @dummy, Anzahl, Preis, @dummy, Datum, Adresse, PLZ, Land) |
@dummy ist eine Variable, der kein Wert zugewiesen wird, so wird diese Spalte einfach ignoriert.
Damit unsere Artikelnummer korrekt importiert wird beschreiben wir das Format der Spalte wie folgt:
Code sql:
1 2 3 | SET ArtikelNr1 = IF(LOCATE('-',ArtikelNr1)>0,
LPAD(SUBSTRING(ArtikelNr1,1,LOCATE('-',ArtikelNr1)-1),5,'0'),
LPAD(ArtikelNr1,5,'0')) |
Mit dem Preis verfahren wir ähnlich, auch hier legen wir das Format der Spalte fest:
Code sql:
1 | SET Preis = REPLACE(Preis, ',', '.')*100 |
Das Problem der Postleitzahl ist ja bereits im Problem der Artikelnummer enthalten gewesen:
Code sql:
1 | SET PLZ = LPAD(PLZ,5,'0') |
Nun kommen wir zu einem schwierigerem Problem, dem Datum. Dazu müssen wir uns noch einmal die Auflistung unserer Spalten ansehen, wir wissen durch @dummy das es erlaubt ist dort Variablen zu definieren, doch wo werden diese Variablen beschrieben?
Eine Möglichkeit ist hier im "SET-Bereich". Also benennen wir die Spalte Datum in @Datum um, dann sieht diese SQL-Zeile wie folgt aus:
Code sql:
1 | (KundenNr, ArtikelNr1, @dummy, Anzahl, Preis, @dummy, @Datum, Adresse, PLZ, Land) |
Code sql:
1 | SET Datum = STR_TO_DATE(@Datum, GET_FORMAT(DATE,'EUR')) |
STR_TO_DATE wandelt ein Datum nach Angabe des Formats ins "Datenbank-Format" um.
GET_FORMAT beschreibt den Aufbau des klassischen europäischen Datumsaufbaus.
Aber warum wurde hier nun der Umweg über eine Variable gewählt, in den vorigen Beispielen haben wir dies nicht benötigt. Das ist ganz einfach zu begründen.
Verwenden wir keine Variablen, wird der Kontext erst importiert und anschließend angepasst. Beim Datum hätten wir dann den Effekt, das etwas Falsches in der Datenbank steht, was wir nun auch nicht mehr korrigieren brauchen.
Daher empfehle ich allgemein mit Variablen zu operieren.
Zur Information, mehrere SET-Befehle werden in einem SET-Block geschrieben und mit Komma getrennt.
Insgesamt sieht der Befehl nun so aus:
Code sql:
1 2 3 4 5 6 7 8 9 10 11 12 | LOAD DATA INFILE '{$file}' INTO TABLE kundentabelle
FIELDS TERMINATED BY ';' ENCLOSED BY ' '
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(KundenNr, @ArtikelNr1, @dummy, Anzahl, @Preis, @dummy, @Datum, Adresse, @PLZ, Land)
SET ArtikelNr1 = IF(LOCATE('-',@ArtikelNr1)>0,
LPAD(SUBSTRING(@ArtikelNr1,1,LOCATE('-',@ArtikelNr1)-1),5,'0'),
LPAD(@ArtikelNr1,5,'0')),
Preis = REPLACE(@Preis, ',', '.')*100,
PLZ = LPAD(@PLZ,5,'0'),
Datum = STR_TO_DATE(@Datum, GET_FORMAT(DATE,'EUR')) |
Ich hoffe ich konnte einen kleinen Einblick gewähren und habe die typischten Beispiele beleuchten können.
Viel Spaß



Kommentar schreiben

Bereiche
Kategorien
Forum - Programming




Artikel bewerten