Bietet Rezepte, Lösungen und ausführliche Beispiele rund um gesundes SQL und zufriedene Datenbanken.
Altdatenübernahme aus Vorgängersystem (Legacy Systemen) gehört zu einer häufigen, aber ziemlich unbeliebten Tätigkeit eines Datenbank- oder Softwareentwicklers. Zumeist wird der Aufwand dafür vollkommen unterschätzt.
* MySQL 5.1.30
* ..auch andere SQL-Datenbanken sollten keine Probleme damit haben.
Ein typisches Problem ist das Normalisieren der seriellen Daten in bestehende Tabellen, denn häufig liefern die Migrationswerkzeuge nur folgenden CSV-Output:
"lfd.Nr","feldname","wert";
"1","kundenr","00001";
"2","name","Musterfrau";
"3","vorname","Meike";
...
"7","kundenr","00002";
"8","name","Mustermann";
...
Zum Einlesen (LOAD) solcher CSV-Daten bieten alle Datenbanken entsprechende Werkzeuge. Nun müssen diese Daten aber in bestehende normalisierte Tabellen eingelesen werden. Und dies geht beispielsweise so:
CREATE TABLE altdaten (
lfdnr integer NOT NULL,
feldname varchar(20),
wert varchar(100),
PRIMARY KEY (lfdnr)
);
INSERT INTO altdaten (lfdnr, feldname, wert) VALUES
('1','knr', '00001'),
('2','name', 'Maier'),
('3','vorname', 'Meike'),
('4','strasse', 'Maiweg 7'),
('5','plz', '12000'),
('6','ort', 'Musterort'),
('7','knr', '00002'),
('8','name', 'Schmitt'),
('9','vorname', 'Stefan'),
('10','strasse', 'Stadtgasse 14'),
('11','plz', '14000'),
('12','ort', 'Musterstadt'),
('13','knr', '00003'),
('14','name', 'Schulz'),
('15','vorname', 'Sonja'),
('16','strasse', 'Ortsgasse 9'),
('17','plz', '16000'),
('18','ort', 'Musterdorf');
Wichtig bei der Analyse der Daten ist die Erkenntnis, dass jede Adresse aus sechs Elementen besteht und eine lückenlose, fortlaufende Nummerierung (Spalte "lfdnr") existiert. Diese Gruppe gilt es nun zu extrahieren und zusammen zu halten.
/**
* MySQL
*/
SELECT (SELECT wert FROM altdaten WHERE lfdnr = gruppe.von_nr ) AS knr,
(SELECT wert FROM altdaten WHERE lfdnr = gruppe.von_nr +1) AS name,
(SELECT wert FROM altdaten WHERE lfdnr = gruppe.von_nr +2) AS vorname,
(SELECT wert FROM altdaten WHERE lfdnr = gruppe.von_nr +3) AS strasse,
(SELECT wert FROM altdaten WHERE lfdnr = gruppe.von_nr +4) AS plz,
(SELECT wert FROM altdaten WHERE lfdnr = gruppe.von_nr +5) AS ort
FROM (SELECT von.lfdnr AS von_nr, bis.lfdnr AS bis_nr
FROM ( SELECT wert, MIN(lfdnr) AS lfdnr
FROM altdaten
WHERE feldname = 'knr'
GROUP BY wert
) von
JOIN ( SELECT wert, MIN(lfdnr) AS lfdnr
FROM altdaten
WHERE feldname = 'ort'
GROUP BY wert
) bis
ON von.lfdnr = bis.lfdnr - 5
) gruppe
ORDER BY gruppe.von_nr;
+-------+---------+---------+---------------+-------+-------------+
| knr | name | vorname | strasse | plz | ort |
+-------+---------+---------+---------------+-------+-------------+
| 00001 | Maier | Meike | Maiweg 7 | 12000 | Musterort |
| 00002 | Schmitt | Stefan | Stadtgasse 14 | 14000 | Musterstadt |
| 00003 | Schulz | Sonja | Ortsgasse 9 | 16000 | Musterdorf |
+-------+---------+---------+---------------+-------+-------------+
3 rows in set (0.03 sec)
Wichtig bei der SQL-Abfrage (Liste 4:) ist die Überprüfung auf das 1. Element der Datengruppe - also das Feld "knr" - sowie auf das letzte Element - die Spalte "ort". Damit die Datengruppe komplett ist, muß zwischen der ersten und der letzten "lfdnr" dieser Gruppe ( 1 - 6 ) der absolute Wert "sechs Elemente" herauskommen. Dann ist die Gruppe komplett.
Die SQL-Abfrage normalisiert die seriellen Daten in ein typisches Tabellenformat. Die Ausgabe kann nun weiter verarbeitet werden.