Daten zusammenführen

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Haben Sie auch Kunden, die ihre Daten in mehreren Datenbanken und/oder Tabellen halten und diese gern zusammenführen möchten Oder kommt das vielleicht sogar bei Ihnen selbst vor Das ist kein Grund zum Schämen: Auch dem Autor dieser Zeilen passiert so etwas. Das ist aber nicht schlimm, wenn man weiß, wie man die Daten zuverlässig in einer einzigen Datenbankanwendung zusammenführt. Im konkreten Fall geht es um zwei Kundendatenbanken für verschiedene Produkte, die vereinigt werden sollten.

Eine Datenbank verwaltet Kunden und deren Abonnements, die andere Kunden und Softwaretools. Es wäre doch toll, wenn es hier einen gemeinsamen Kundenstamm gäbe. Sonst hilft einem etwa die Erkenntnis, dass ein Kunde nicht gern Rechnungen bezahlt, gar nichts, wenn seine nächste Bestellung von einer völlig anderen Datenbank verwaltet wird.

Gäbe es nur einen Kunden-Stammdatensatz in einer einzigen Datenbank mit allen Produkten, könnte man gleich den Riegel vorschieben und beispielsweise Vorkasse verlangen, wenn ein säumiger Kunde mal wieder eine Bestellung aufgibt.

Andersherum lassen sich in einer einzigen Datenbank viel einfacher Rabattaktionen für Kunden durchführen, die gegebenenfalls schon mehrere Produkte erworben haben – und vieles mehr. Und generell tut es gut, wenn man weiß, dass es Stammkunden gibt, die immer wieder auf die angebotenen Produkte zugreifen. Bis dahin ist es allerdings ein langer Weg, wenn die Kundendaten sich noch nicht in einer einzigen Datenbank befinden.

Von Südwind zu Südwind

In diesem Beitrag schauen wir uns beispielhaft anhand der Südwind-Datenbank an, wie Sie die Daten der einen Datenbank zu denen der anderen Datenbank hinzufügen können. Vereinfachend gehen wir davon aus, dass Sie schlicht zwei gleich aufgebaute Datenbanken verwenden, um unterschiedliche Produkte zu verwalten – beispielsweise für einen Lebensmittel-Shop und einen Shop mit Haarpflegeprodukten.

Die Daten der eigentlichen Südsturm-Datenbank (unserer optimierten Version der Nordwind-Datenbank) haben wir beibehalten, zusätzlich verwenden wir eine Kopie der Südsturm-Datenbank, die allerdings in der Artikeltabelle nur Haarpflegeprodukte enthält. Außerdem gibt es dort andere Mitarbeiter, Kategorien, Kunden, Lieferanten et cetera – genug Material also, um einen Import zu programmieren.

Vorhandene Daten

Wichtig ist vorab, dass Sie für jede Tabelle den Umgang mit vorhandenen Daten klären. Sollen vorhandene Datensätze, die in bestimmten Kriterien mit einem neuen Datensatz übereinstimmen, ersetzt werden Oder behalten Sie den vorhandenen Datensatz bei Und welche Kriterien legen überhaupt fest, ob der Datensatz als vorhanden definiert wird

Primärschlüsselwerte

Wie geht man mit zu importierenden Datensätzen um, deren Primärschlüsselwert bereits vorhanden ist Eines ist klar: Zweifach können Sie keinen Primärschlüsselwert vergeben. Also müssen Sie dem neuen Datensatz einen neuen Primärschlüsselwert zuweisen.

Fremdschlüsselfelder

An sich kein Problem, wenn da die verknüpften Tabellen nicht wären: Wenn Sie beispielsweise einen Artikel neu anlegen und dessen Primärschlüsselwert dabei ebenfalls neu vergeben, müssen Sie bei zu importierenden Daten, die mit dem Artikel verknüpft sind, auch die Fremdschlüsselfelder anpassen.

Dies erledigen wir in diesem Fall auf einfache Weise: Wir fügen den Tabellen der Zieldatenbank ein neues Feld hinzu, das PKAlt heißt. Bei neu eingefügten Datensätzen schreiben wir den alten Primärschlüsselwert als Erinnerung in dieses Feld. Wenn Sie dann später etwa eine Bestellposition importieren, die einen solchen Artikel referenziert, brauchen Sie nur zu prüfen, welcher Artikeldatensatz in der Zieltabelle den Fremdschlüsselwert im Feld PKAlt aufweist. Dann ermitteln Sie den neuen Primärschlüsselwert dieses Datensatzes und tragen ihn als neuen Wert des entsprechenden Fremdschlüsselfeldes der Bestellposition ein.

Reihenfolge der Tabellen

Auch die Reihenfolge der Tabellen beim Import ist wichtig. Tabellen, die Fremdschlüsselfelder mit Verknüpfungen zu anderen Tabellen enthalten, können Sie erst importieren, wenn die entsprechenden Datensätze der verknüpften Tabellen vorliegen. Im Falle der Südsturm-Datenbank sähe dies wie folgt aus:

  • tblKategorien (keine Fremdschlüsselfelder)
  • tblPersonal (keine Fremdschlüsselfelder)
  • tblLieferanten (keine Fremdschlüsselfelder)
  • tblVersandfirmen (keine Fremdschlüsselfelder)
  • tblKunden (keine Fremdschlüsselfelder)
  • tblArtikel (verknüpft mit tblKategorien und tblLieferanten)
  • tblBestellungen (verknüpft mit tblKunden, tblPersonal und tblLieferanten)
  • tblBestellpositionen (verknüpft mit tblBestellungen und tblArtikel)

Zugriff auf die zu importierenden Daten

Auf die Quelldaten für den Import können Sie auf verschiedene Arten zugreifen. Am einfachsten ist es vermutlich, die Tabellen einfach zu verknüpfen. Sie liegen dann wie lokale Tabellen vor und können per VBA genau so behandelt werden.

Eine zweite Variante ist es, die Tabellen nicht zu verknüpfen, sondern mit der IN-Klausel in SELECT– Statements auf die Daten zuzugreifen. Dies ist jedoch etwas unübersichtlicher, da man auch nicht mal eben ein paar Werte in den betroffenen Tabellen prüfen kann, ohne die Quelldatenbank zu öffnen.

Kategorien zusammenführen

Beginnen wir mit einer kleinen Aufwärmübung: dem Zusammenführen der Datensätze der Tabelle tblKategorien. Die Quelltabelle ist in der Zieldatenbank in Form einer Verknüpfung eingebunden und heißt tblKategorien1. Das Zusammenführen übernimmt in diesem Fall die Prozedur aus Listing 1.

Listing 1: Zusammenführen der beiden Tabellen tblKategorien und tblKategorien1

Public Sub DatenZusammenfuehren()
    Dim db As DAO.Database
    Dim rstQuelle As DAO.Recordset
    Dim rstZiel As DAO.Recordset
    Dim lngZielID As Long
    Set db = CurrentDb
    Set rstQuelle = db.OpenRecordset("SELECT * FROM tblKategorien1", dbOpenDynaset)
    Set rstZiel = db.OpenRecordset("SELECT * FROM tblKategorien", dbOpenDynaset)
    Do While Not rstQuelle.EOF
        lngZielID = Nz(DLookup("KategorieID", "tblKategorien", "Kategoriename = ''" _
            & rstQuelle!Kategoriename & "''"))
        If lngZielID = 0 Then
            rstZiel.AddNew
            rstZiel!Kategoriename = rstQuelle!Kategoriename
            rstZiel!Beschreibung = rstQuelle!Beschreibung
            rstZiel!Abbildung = rstQuelle!Abbildung
            rstZiel!PKAlt = rstQuelle!KategorieID
            rstZiel.Update
        Else
            rstZiel.FindFirst "KategorieID = " & lngZielID
            rstZiel.Edit
            rstZiel!PKAlt = rstQuelle!KategorieID
            rstZiel.Update
        End If
        rstQuelle.MoveNext
    Loop
    Set db = Nothing
End Sub

Die Prozedur deklariert zunächst ein Database-Objekt und zwei Recordset-Objekte – je eines für die Quell- und die Zieldatenbank. Außerdem benötigen wir eine Variable, welche den Wert eines Datensatzes mit einer eventuell bereits vorhandenen Kategorie speichert. Danach weist die Prozedur den Objekten den Verweis auf die aktuelle Datenbank sowie auf die beiden betroffenen Tabellen zu. Eine Do While-Schleife durchläuft die Quelltabelle und prüft zunächst, ob die Zieltabelle bereits eine gleichnamige Kategorie enthält.

Ist dies der Fall, wird die Variable lngZielID mit dem Wert des Primärschlüsselwertes des entsprechenden Datensatzes gefüllt. Ist noch keine Kategorie dieses Namens vorhanden, erhält lngZielID den Wert 0.

In diesem Fall wird der Tabelle ein neuer Datensatz hinzugefügt. Das Erstellen des neuen Datensatzes erledigt die AddNew-Methode des Recordset-Objekts.

Die folgenden Zeilen weisen den jeweiligen Feldern die Werte aus dem Quelldatensatz zu – außer einem Feld: Das Primärschlüsselfeld KategorieID ist ein Autowertfeld, das seinen Wert automatisch erhält. Schließlich speichert die Update-Anweisung den neuen Datensatz.

Ist bereits eine gleichnamige Kategorie vorhanden, hat lngZielID einen Wert ungleich 0. Die Prozedur sucht in diesem Fall mit der FindFirst-Methode nach dem entsprechenden Datensatz und verschiebt den Datensatzzeiger auf diesen Datensatz.

Dann bereitet sie diesen mit der Edit-Methode zum ändern vor. Die einzige änderung ist der Eintrag des Primärschlüsselwertes des Datensatzes aus der Quelltabelle in das Feld PKAlt der Zieltabelle. Die Update-Methode speichert die änderung in der Tabelle. Das Ergebnis sieht dann beispielsweise wie in Bild 1 aus.

pic001.png

Bild 1: Zieltabelle mit Angabe der Primärschlüsselwerte der Quelltabelle

Auf die gleiche Weise fügen wir einige Zeilen Code zur Prozedur hinzu, welche die Lieferanten der Quelldatenbank zur Tabelle tblLieferanten der Zieltabelle hinzufügt. Die Unterschiede finden sich lediglich in den verwendeten Tabellen und Feldnamen. Auch für die Tabelle tblLieferanten gilt: Die Datensätze der Tabelle tblArtikel sind über das Feld LieferantID mit den Lieferanten-Datensätzen verknüpft.

Damit wir später ermitteln können, wie der neue Primärschlüsselwert eines importierten Lieferanten-Datensatzes lautet, müssen wir auch den alten Wert in der Zieltabelle speichern. Dafür legen Sie auch hier ein neues Feld namens PKAlt an.

Daten mit Verknüpfungen hinzufügen

Prinzipiell unterscheidet sich das Hinzufügen von Daten aus Tabellen, für die bereits über Fremdschlüsselfelder verknüpfte Daten in der Zieltabelle vorliegen, kaum von dem oben beschriebenen Vorgang zum Einlesen einfacher Daten ohne Verknüpfung. Die Erweiterung aus Listing 2 zeigt, wie der benötigte Code aussieht.

Listing 2: Zusammenführen von Kategorien, Lieferanten und Artikeln in einem Rutsch

Public Sub DatenZusammenfuehren_KategorienLieferantenArtikel()
    Dim db As DAO.Database
    Dim rstQuelle As DAO.Recordset
    Dim rstZiel As DAO.Recordset
    Dim lngZielID As Long
    Set db = CurrentDb
    ''... Kategorien hinzufügen
    ''... Lieferanten hinzufügen    
    Set rstQuelle = db.OpenRecordset("SELECT * FROM tblArtikel1", dbOpenDynaset)
    Set rstZiel = db.OpenRecordset("SELECT * FROM tblArtikel", dbOpenDynaset)
    Do While Not rstQuelle.EOF
        lngZielID = Nz(DLookup("ArtikelID", "tblArtikel", "Artikelname = ''" _
            & rstQuelle!Artikelname & "''"))
        If lngZielID = 0 Then
            rstZiel.AddNew
            rstZiel!Artikelname = rstQuelle!Artikelname
            rstZiel!LieferantID = DLookup("LieferantID", "tblLieferanten", "PKAlt = " _
                & rstQuelle!LieferantID)
            rstZiel!KategorieID = DLookup("KategorieID", "tblKategorien", "PKAlt = " _
                & rstQuelle!KategorieID)
            rstZiel!Liefereinheit = rstQuelle!Liefereinheit
            rstZiel!Einzelpreis = rstQuelle!Einzelpreis
            rstZiel!Lagerbestand = rstQuelle!Lagerbestand
            rstZiel!BestellteEinheiten = rstQuelle!BestellteEinheiten
            rstZiel!Mindestbestand = rstQuelle!Mindestbestand
            rstZiel!Auslaufartikel = rstQuelle!Auslaufartikel
            rstZiel!PKAlt = rstQuelle!ArtikelID
            rstZiel.Update
        Else
            rstZiel.FindFirst "ArtikelID = " & lngZielID
            rstZiel.Edit
            rstZiel!PKAlt = rstQuelle!ArtikelID
            rstZiel.Update
        End If
        rstQuelle.MoveNext
    Loop
    Set db = Nothing
End Sub

Genau genommen finden sich nur beim Eintragen der Werte der Fremdschlüsselfelder Unterschiede: Sie können dort natürlich nicht einfach den Wert des Feldes aus der Originaltabelle anlegen, sondern müssen prüfen, welchen Primärschlüsselwert der verknüpfte Datensatz in der Zieltabelle aufweist.

Genau für diesen Zweck haben wir in den Zieltabellen das Feld PKAlt eingerichtet. Um zu ermitteln, wie der neue Primärschlüsselwert lautet, sucht die Prozedur zunächst nach dem Datensatz, dessen Wert im Feld PKAlt mit dem im Fremdschlüsselfeld der Tabelle tblArtikel angegebenen Wert übereinstimmt. Zu diesem Datensatz benötigen Sie dann nur noch den Wert des Primärschlüsselfeldes und tragen diesen in das Fremdschlüsselfeld des neuen Datensatzes ein. Wie dies schematisch aussieht, erfahren Sie in Bild 2.

pic002.png

Bild 2: Schematischer Ablauf beim Ermitteln des neuen Fremdschlüsselwertes eines importierten Datensatzes

In der Prozedur verwenden Sie für diesen Zweck schlicht zwei Aufrufe der DLookup-Funktion. Diese greift auf die Daten der verknüpften Zieltabellen zu, also beispielsweise auf die Tabelle tblKategorien. Als Kriterium kommt ein Ausdruck zum Einsatz, der nach der Kategorie sucht, deren Feld PKAlt den Wert aufweist, den das Fremdschlüsselfeld KategorieID der Tabelle tblArtikel1 (also der Quelltabelle) enthält.

Zu genau diesem Datensatz ermittelt DLookup dann den Primärschlüsselwert, also den neuen Wert des Fremdschlüsselfeldes KategorieID in der Zieltabelle tblArtikel.

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar