Warum noch ein Access-Buch?
Für wen ist das Buch?
Jetzt bestellen
+ direkter Download des eBooks!
Nur EUR 59,95!
Fehler gefunden?
Bitte melden!
Wünsche an das Buch?
Her damit!
Was denken die Leser über dieses Buch?
Lesen Sie aktuelle Rezensionen!
Kapitel des noch nicht veröffentlichten Buchs zum Downloaden, Probelesen und Kommentieren
Beispieldatenbanken
Zusätzliches Material

Das Buch im HTML-Format

Für unbestimmte Zeit bieten Addison-Wesley und André Minhorst den kompletten Inhalt des Buchs als Download an. Schauen Sie rein und informieren Sie sich über den Inhalt! Und wenn Ihnen das Buch nützlich erscheint und Sie glauben, dass Sie etwas gelernt haben oder durch das Gelesene sogar etwas Zeit und somit Geld bei Ihrer Arbeit einsparen konnten, können Sie sich ja beim Autor und beim Verlag revanchieren - beispielsweise durch den Kauf dieses Buchs.

Am schönsten wäre es natürlich, wenn Sie das Buch direkt hier bestellen - Sie erhalten das Buch dann direkt vom Verlag, und der Autor und Verlag haben dann noch mehr davon, als wenn Sie es anderswo kaufen.

Danke für Ihr Interesse!

2.3 Normalisierung

2.3.1 Die erste Normalform

Die erste Normalform fordert, dass jede in einem Feld gespeicherte Information atomar ist und nicht mehr in weitere Informationen unterteilt werden kann. Dadurch erreichen Sie, dass Sie die enthaltenen Werte einfach abfragen oder sortieren können. Beispiele für nicht atomare Informationen sind folgende in einem einzigen Feld gespeicherte Informationen:

  • Vorname und Nachname
  • Straße, Hausnummer, PLZ und Ort
  • Wenn eine Tabelle ein Feld mit der Bezeichnung Name enthält und dieses sowohl den Vor- und den Nachnamen (in dieser Reihenfolge) wiedergibt, können Sie beispielsweise nur schwer nach dem Nachnamen sortieren. Vor- und der Nachname sind daher unbedingt in zwei Feldern zu speichern.

    Bei der Adresse bietet sich ein ähnliches Bild: Nach Datensätzen mit einem bestimmten Ort oder einer bestimmten PLZ wird oft gesucht. Diese Informationen sollten Sie daher in separaten Feldern speichern (siehe Abbildung 2.29 und Abbildung 2.30).

    Etwas anders sieht es bei der Straße und der Hausnummer aus: Die Angabe einer Straße hat ohne die Hausnummer zwar noch einen gewissen Informationsgehalt (wenn Sie zum nächsten IKEA fahren möchten, kommen Sie wahrscheinlich ohne die Angabe der Hausnummer aus), aber andersherum lässt sich mit einer Hausnummer allein wenig anfangen. Und das Sortieren danach macht in den meisten Fällen auch keinen Sinn. Fazit: Straße und Hausnummer sind quasi atomar und gehören deshalb normalerweise in ein Feld. Und dort, wo diese Regel durch eine Ausnahme bestätigt wird, werden die Anforderungen schon durchblicken lassen, dass die Informationen besser in getrennte Felder gehören.

    Abbildung 2.29: Tabelle mit Personendaten vor ...

    Abbildung 2.30: ... und nach der Atomisierung

    Um den Inhalt des Feldes Name aus Abbildung 2.29 in die beiden Felder Vorname und Nachname aus Abbildung 2.30 zu überführen, ist zumindest eine regelmäßige Anordnung des zusammengesetzten Feldes erforderlich - also entweder immer oder , . Dann lassen sich die Daten leicht von der einen in die andere Tabelle überführen, etwa mit folgender Prozedur:

    Public Sub NameAufteilen()

        Dim db As DAO.Database
        Dim rst As DAO.Recordset
        Dim longPos As Long
        Dim strName As String
        Dim strVorname As String
        Dim strNachname As String
        Dim strSQL As String
        Dim lngLastSpace As Long

        Set db = CurrentDb
        Set rst = db.OpenRecordset("tblPersonenNichtNormalisiert", _
            dbOpenDynaset)

        Do While Not rst.EOF
            strName = rst!Name
            lngLastSpace = InStrRev(strName, " ")

            strVorname = Mid(strName, 1, lngLastSpace)
            strNachname = Mid(strName, lngLastSpace + 1)

            strSQL = "INSERT INTO tblPersonenNormalisiert(Vorname, " _
                & "Nachname) VALUES('" & strVorname & "','" & strNachname & "')"
            db.Execute strSQL

            rst.MoveNext
        Loop

    End Sub

    Listing 2.1: Extrahieren der Bestandteile des Feldes Name in Vor- und Nachname

    Die Prozedur geht davon aus, dass die Reihenfolge ist und dass der Nachname keine Leerzeichen enthält. Sie schreibt den Teil des Namens hinter dem letzten Leerzeichen in das Feld Nachname und den Rest in das Feld Vorname.

    Wenn der Name auch mal in der anderen Reihenfolge und durch Komma getrennt angegeben ist, können Sie dies durch eine entsprechende Verfeinerung der Prozedur abfangen. Aber Unarten, wie zuerst den Nachnamen und dann den Vornamen zu schreiben, ohne dazwischen ein Komma einzufügen, sind leider ebenfalls gängig; hier hilft wohl nur manuelles Nacharbeiten.

    Ein anderes Beispiel, das nach der ersten Normalform schreit, sind mehrere gleichartige Informationen in Listenform in einem einzigen Feld wie in Abbildung 2.31.

    Abbildung 2.31: Beispiel für nicht atomare Informationen

    Ein erster naiver Ansatz, die im Feld Lieferanten enthaltenen Daten in atomare Feldinhalte umzuwandeln, sieht wie in Abbildung 2.32 aus.

    Das ist eine oft zu beobachtende Variante, um gleichartige Informationen zu einem Datensatz zu speichern. Leider birgt diese Variante mindestens drei Schwächen:

  • Früher oder später gibt es einen Artikel, der mehr Lieferanten als dafür vorgesehene Felder hat. Dann heißt es: Felder anfügen, Abfragen anpassen, Formulare anpassen, Code anpassen.
  • Wenn ein Artikel weniger Lieferanten als dafür vorgesehene Felder hat, bleiben diese leer und verschwenden unnötig Platz.
  • Wenn man nach Artikeln mit einem bestimmten Lieferanten sucht, muss man alle dafür vorgesehenen Felder durchgehen.
  • Abbildung 2.32: Atomar, aber nicht optimal: Felder mit gleichartigen Informationen

    In diesem Fall gibt es nur eine Lösung: Da theoretisch jeder Artikel von jedem Lieferanten geliefert werden kann, muss eine m:n-Beziehung her. Das bedeutet, dass die Lieferanten in einer eigenen Tabelle gespeichert werden.

    Welcher Lieferant welchen Artikel liefert, speichern Sie in einer Verknüpfungstabelle, die jeweils die Nummer des Artikels und des Lieferanten aufnimmt.

    Das aus der Tabelle in Abbildung 2.32 entstehende Datenmodell sieht wie in Abbildung 2.33 aus.

    Abbildung 2.33: Manchmal führt Atomatisieren zu m:n-Beziehungen

    Um Daten wie aus der Tabelle tblArtikel_1 in Abbildung 2.32 in die Tabellen einer solchen m:n-Beziehung zu überführen, verwenden Sie etwa den Code aus folgendem Listing.

    Public Sub AtomizeIntoMNRelation()

        Dim db As DAO.Database
        Dim rstArtikel As DAO.Recordset
        Dim rstLieferanten As DAO.Recordset
        Dim strLieferant As String
        Dim fld As DAO.Field
        Dim lngLieferantID As Long

        Set db = CurrentDb
        Set rstArtikel = db.OpenRecordset("tblArtikel_1", dbOpenDynaset)

        'Alle Datensätze der Datensatzgruppe rstArtikel durchlaufen
        Do While Not rstArtikel.EOF

            'Für alle Felder der Tabelle...
            For Each fld In rstArtikel.Fields

                '...kontrolliere, ob der Name mit 'Lieferant' beginnt
                If Left(fld.Name, 9) = "Lieferant" _
                    And Not IsNull(fld.Value) Then                

                    'Prüfen, ob schon ein Lieferant mit diesem Namen
                    'vorhanden ist
                    strLieferant = fld.Value
                    Set rstLieferanten = db.OpenRecordset _
                        ("SELECT * FROM tblLieferanten WHERE Lieferant = '" _
                        & DoubleQuotes(strLieferant) & "'", dbOpenDynaset)

                    'Wenn noch nicht vorhanden, Lieferant
                    'in tblLieferanten anlegen
                    If rstLieferanten.RecordCount = 0 Then
                        rstLieferanten.AddNew
                        rstLieferanten!Lieferant = strLieferant

                        'LieferantID merken
                        lngLieferantID = rstLieferanten!LieferantID
                        rstLieferanten.Update
                    Else
                        lngLieferantID = rstLieferanten!LieferantID
                    End If
                End If

                'Neuen Datensatz in Verknüpfungstabelle anlegen
                db.Execute "INSERT INTO tblArtikelLieferanten(ArtikelID, " _
                    & "LieferantID) VALUES(" & rstArtikel!ArtikelID _
                    & ", " & lngLieferantID & ")"

            Next fld
            rstArtikel.MoveNext

        Loop

    End Sub

    Listing 2.2: Aufbrechen nicht atomarer Informationen in eine m:n-Beziehung

    Das Resultat dieser Prozedur für die Daten aus der in Abbildung 2.32 gezeigten Tabelle finden Sie in Abbildung 2.34. Die Prozedur durchläuft alle Datensätze der ursprünglichen Tabelle und unterzieht die Inhalte aller Felder, deren Feldname mit Lieferant beginnt (also Lieferant1, Lieferant2 ...) und deren Feldinhalt nicht leer ist, einer gesonderten Behandlung: Zunächst wird überprüft, ob die Tabelle tblLieferanten bereits einen Lieferanten mit dem angegebenen Namen enthält. Falls nein, wird ein entsprechender Datensatz in dieser Tabelle angelegt. Der Wert des Feldes LieferantID wird in jedem Fall festgehalten, um in einer abschließenden Aktionsabfrage einen neuen Datensatz in der Verknüpfungstabelle tblArtikelLieferanten anzulegen.

    Fast für jede Vorgehensweise gibt es Alternativen. Ein passendes Beispiel für das Anfügen verknüpfter Daten finden Sie in Kapitel 13, Abschnitt 13.3.8 »Funktionale Fehlerbehandlung«.

    Abbildung 2.34: Diese Daten entsprechen der ersten Normalform

    Nächster Abschnitt:

    2.3.2 Die zweite Normalform

    © 2006-2008 André Minhorst Alle Rechte vorbehalten.