Springe zum Hauptinhalt

Vom Download zur Datenbank

Für ein privates Projekt brauchte ich die aktuellen deutschen Bankleitzahlen. Die Bundesbank stellt diese Daten auf ihrer Webseite als Download zur Verfügung. Die Daten gibt es gepackt (als ZIP-Datei) oder ungepackt für Excel (.xslx), für Lotus Notes (.nsf) oder aber als Textdatei mit festen Spaltenbreiten (*.txt). Zur Bearbeitung unter Linux eignet sich letztere Variante natürlich besonders. Aber in dieser Form konnte ich die Daten nicht wirklich gut in meinem Projekt einsetzen. Eine Datenbankdatei erschien mir in vielerlei Hinsicht besser geeignet. Und den Weg vom Download bis zur Datenbank soll dieser Blogbeitrag beschreiben.

Die Textdatei der Bundesbank liegt in der Kodierung ISO 8859-15 vor. Heutzutage wird üblicherweise UTF-8 als Kodierung eingesetzt. Zur Konvertierung bietet sich unter Linux das Tool iconv an. Eine Beschreibung dazu findet sich z. B. auf der Seite von Arch Linux.

Zur Umwandlung der Textdatei in eine entsprechende SQL-Datei zum Import in eine Datenbank habe ich mich dann für die Skriptsprache awk entschieden. Denn awk kann das inzwischen eher selten gewordene Format Text mit festen Spaltenbreiten durch die Angabe der Feldbreiten recht einfach einlesen.

Im letzten Schritt folgt dann der Import der SQL-Datei in die Datenbank. Als Datenbanksystem nutze ich SQLite.

Den kompletten Workflow habe ich mit einem Shellskript und einem awk-Skript realisiert. Das Shellskript fasst die einzelnen o. g. Schritte zusammen und sieht folgendermaßen aus:

#!/bin/bash

URL="https://www.bundesbank.de/resource/blob/602632/ee217442b4c4619dfeb50ec4c7a5f995/mL/blz-aktuell-txt-data.txt"

wget --output-document=blz.txt $URL

touch ./blz.db

./blz2sql.awk blz.txt|\
iconv --from-code ISO-8859-15 --to-code UTF-8 |\
sqlite3 ./blz.db

Das awk-Skript hat folgenden Aufbau:

#!/usr/bin/awk -f

function trim(v)
{
  gsub(/^[ ]+|[ ]+$/, "", v);
  return v;
}


BEGIN {
  FIELDWIDTHS = "8 1 58 5 35 27 5 11 2 6 1 1 8";
  print "PRAGMA encoding = \"UTF-8\";";
  print "PRAGMA synchronous = OFF;";
  print "PRAGMA default_synchronous = OFF;";
  print;
  print "DROP TABLE IF EXISTS BANKLEITZAHLEN;";
  print;
  print "CREATE TABLE BANKLEITZAHLEN (";
  print "  BANKLEITZAHL TEXT,";
  print "  BLZZD TEXT,";
  print "  BEZEICHNUNG TEXT,";
  print "  POSTLEITZAHL TEXT,";
  print "  ORT TEXT,";
  print "  KURZBEZEICHNUNG TEXT,";
  print "  INSTITUTSNUMMERPAN TEXT,";
  print "  BIC TEXT,";
  print "  PZBM TEXT,";
  print "  DSNUM TEXT,";
  print "  AENDKZ TEXT,";
  print "  BLZLOESCH TEXT,";
  print "  NFBLZ TEXT";
  print "  IBANRKZ TEXT";
  print ");";
  print
  print "BEGIN TRANSACTION;";
}

{
  printf "  INSERT INTO BANKLEITZAHLEN VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');\n",\
         $1, $2, trim($3), $4, trim($5), trim($6), trim($7), trim($8), $9, $10, $11, $12, $13;
}

END {
  print "COMMIT;";
}

Die Hilfsfunktion trim schneidet bei den Feldern vorne und hinten die Leerzeichen ab. Im Abschnitt BEGIN werden mit FIELDWIDTHS die Feldbreiten festgelegt um dann die Beschreibung der Tabellenstruktur in SQL zu erzeugen und eine Transaktion für die im Hauptabschnitt folgenden INSERT-Statements zu starten.

Im Abschnitt END wird dann nur noch die Transaktion mit einem COMMIT beendet. Die erzeugte SQL-Datei kann dann unmittelbar in die Datenbank überführt werden.