Gleich vorweg:
Ich hatte ein Problem, zu dem ich zunächst im Internet eine Lösung gesucht habe. Dabei habe ich aber nur gelernt, dass viele vor mir schon das gleiche Problem hatten - eine Lösung war nicht dabei.
Inzwischen habe ich aber selbst eine Lösung gefunden, die ich für Interessierte hier gerne hinterlegen möchte.
################################
Beim Einspielen von Daten in eine MySQL (genauer gesagt, 5.5.29-MariaDB) gehe ich wie folgt vor:
Ich entwerfe pro Tabelle die hinzuzufügenden Zeilen in einem Tabellenkalkulationsprogramm (z.B. gnumeric).
Dieses verwende ich v.a. als angenehmen übersichtlichen Editor für Tabellen mit ein paar Zusatzfunktionen, z.B. um die Eindeutigkeit der Schlüssel vorab zu prüfen oder auch Strings zu bearbeiten.
Dann erstelle ich daraus eine Tabulator-getrennte Textdatei (Kopieren aus dem Programm in Text-Editor).
Diese Datei hoffte ich dann, in die Datenbank einspielen zu können mit einem Befehl wie
Das funktioniert auch - mit einer unschönen Nebenwirkung:
Im Tabellenverabeitungsprogramm nicht gefüllte Zellen werden mit einem Standardwert gefüllt, also leere Zeichenkette bei VARCHAR, 0 bei INT, '0000-00-00' bei DATE usw.
Häufig - insbesondere bei mir - ist aber gewünscht, dass diese Felder auf der Datenbank ungefüllt bleiben, also mit NULL-Werten.
NULL-Werte aber soll man in solchen Einspieldateien durch \N kennzeichnen.
Wer hat schon Lust, alle leeren Zellen mit \N vollzukopieren?
Wenn MySQL schon nicht nachgibt, muss man das wenigstens automatisieren.
Wie erkennt man in der (halb-)fertigen Einspieldatei, dass ein leeres Feld eingespielt werden soll?
Antwort: Zwei Feldbegrenzer - hier Tabulatoren - stoßen unmittelbar aufeinander.
Hier ist also immer ein "\N" einzufügen.
Ein einfacher Suchen-und-Ersetzen-Vorgang genügt aber nicht, da von zwei aufeinanderfolgenden leeren Feldern nur immer das erste angepasst würde.
Man muss den Prozess also iterieren.
Hier ist meine vollständige Lösung für das Problem:
Ich rufe im Verzeichnis mit der Einspieldatei (nach dem Speichern als Text, vor dem Einspielen) folgenden Befehl auf:
Dies nimmt genau die oben erläuterten Ersetzungen vor,
und die Einspielung führt zum gewünschten Ergebnis.
Randbemerkung: Das Kennzeichen "g" im obigen Befehl kann man auch weglassen. Das Ergebnis ist dasselbe, die Laufzeit u.U. eine andere.
Allerdings: Meine Infiles sind klein, mein Herz ist rein, und ich kann nicht erkennen, in welcher Richtung der Performanz-Vorteil zu finden ist.
################################
Falls jemand bessere Lösungen kennt, freue ich mich sehr, sie zu erfahren!
In jedem Fall hoffe ich, dass ich anderen auf der Suche einige Experimente ersparen kann.
Ich hatte ein Problem, zu dem ich zunächst im Internet eine Lösung gesucht habe. Dabei habe ich aber nur gelernt, dass viele vor mir schon das gleiche Problem hatten - eine Lösung war nicht dabei.
Inzwischen habe ich aber selbst eine Lösung gefunden, die ich für Interessierte hier gerne hinterlegen möchte.
################################
Beim Einspielen von Daten in eine MySQL (genauer gesagt, 5.5.29-MariaDB) gehe ich wie folgt vor:
Ich entwerfe pro Tabelle die hinzuzufügenden Zeilen in einem Tabellenkalkulationsprogramm (z.B. gnumeric).
Dieses verwende ich v.a. als angenehmen übersichtlichen Editor für Tabellen mit ein paar Zusatzfunktionen, z.B. um die Eindeutigkeit der Schlüssel vorab zu prüfen oder auch Strings zu bearbeiten.
Dann erstelle ich daraus eine Tabulator-getrennte Textdatei (Kopieren aus dem Programm in Text-Editor).
Diese Datei hoffte ich dann, in die Datenbank einspielen zu können mit einem Befehl wie
Code:
load data local infile '/lokaler/pfad/zur/gewünschten/datei.tab' into table tabelle fields terminated by '\t' escaped by '\\' lines terminated by '\n';
Das funktioniert auch - mit einer unschönen Nebenwirkung:
Im Tabellenverabeitungsprogramm nicht gefüllte Zellen werden mit einem Standardwert gefüllt, also leere Zeichenkette bei VARCHAR, 0 bei INT, '0000-00-00' bei DATE usw.
Häufig - insbesondere bei mir - ist aber gewünscht, dass diese Felder auf der Datenbank ungefüllt bleiben, also mit NULL-Werten.
NULL-Werte aber soll man in solchen Einspieldateien durch \N kennzeichnen.
Wer hat schon Lust, alle leeren Zellen mit \N vollzukopieren?
Wenn MySQL schon nicht nachgibt, muss man das wenigstens automatisieren.
Wie erkennt man in der (halb-)fertigen Einspieldatei, dass ein leeres Feld eingespielt werden soll?
Antwort: Zwei Feldbegrenzer - hier Tabulatoren - stoßen unmittelbar aufeinander.
Hier ist also immer ein "\N" einzufügen.
Ein einfacher Suchen-und-Ersetzen-Vorgang genügt aber nicht, da von zwei aufeinanderfolgenden leeren Feldern nur immer das erste angepasst würde.
Man muss den Prozess also iterieren.
Hier ist meine vollständige Lösung für das Problem:
Ich rufe im Verzeichnis mit der Einspieldatei (nach dem Speichern als Text, vor dem Einspielen) folgenden Befehl auf:
Code:
/lokaler/pfad/zur/gewünschten> perl -i.old -pe 's/\t\t/\t\\N\t/g while /\t\t/' datei.tab
Dies nimmt genau die oben erläuterten Ersetzungen vor,
und die Einspielung führt zum gewünschten Ergebnis.
Randbemerkung: Das Kennzeichen "g" im obigen Befehl kann man auch weglassen. Das Ergebnis ist dasselbe, die Laufzeit u.U. eine andere.
Allerdings: Meine Infiles sind klein, mein Herz ist rein, und ich kann nicht erkennen, in welcher Richtung der Performanz-Vorteil zu finden ist.
################################
Falls jemand bessere Lösungen kennt, freue ich mich sehr, sie zu erfahren!
In jedem Fall hoffe ich, dass ich anderen auf der Suche einige Experimente ersparen kann.