Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 5/2005.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Erfahren Sie, wie Sie überflüssige Daten archivieren und diese bei Bedarf wiederherstellen, und umgehen gängige Fallstricke.

Techniken

Tabellen, SQL-Aktionsabfragen, Autowerte, GUID

Voraussetzungen

Access 97 oder höher

Beispieldateien

Archivierung97.mdb, Archivierung00.mdb

Daten archivieren und wiederherstellen

André Minhorst, Duisburg

In Access-Datenbanken kann man zwar recht große Datenmengen speichern, aber bei zwei Gigabyte ist Schluss. Wenn man an diese Grenze stößt oder aus anderen Gründen die Datenmenge reduzieren möchte - etwa um eine bessere Leistung zu erzielen -, kann man Daten archivieren. Wie Sie dabei vorgehen und gleichzeitig sicherstellen, dass die Daten sich ohne Probleme wieder herstellen lassen, erfahren Sie im vorliegenden Beitrag.

Daten archivieren

Das Archivieren von Daten erfolgt meist durch Kopieren der Daten in eine externe Datenbank. Normalerweise werden Daten in einem bestimmten Zeitintervall archiviert - etwa einmal im Monat, einmal im Jahr oder auch öfter. Das Intervall hängt davon ab, nach welchem Zeitraum Daten nicht mehr regelmäßig benötigt werden und daher im laufenden Betrieb nicht mehr zugänglich sein müssen.

Wer etwa eine Bestellverwaltung betreibt, dürfte sich von den Daten einer Bestellung beispielsweise nach Ablauf der Garantiefrist beziehungsweise Gewährleistungsfrist verabschieden können.

Sinnvoll ist es, die zu archivierenden Daten in der gleichen oder einer ähnlichen Form zu speichern - am besten in einer Access-Datenbank, deren Tabellen genau wie in der Originaldatenbank aufgebaut sind.

Das Archivieren selbst läuft in einer oder mehreren SQL-Aktionsabfragen ab, wobei die Daten zunächst in die Archivdatenbank kopiert und dann aus der Originaldatenbank gelöscht werden.

Dabei ist die Reihenfolge der Vorgänge nicht unwichtig: So sollten Sie beispielsweise bei Daten aus verknüpften Tabellen zunächst die Daten der Mastertabellen und dann erst die Daten der Detailtabellen archivieren, da sonst eventuell festgelegte referentielle Integrität nicht durchgesetzt werden kann.

Man kann in der Archivdatenbank natürlich auch auf das Festlegen von Beziehungen verzichten und einfach nur die Daten in die jeweiligen Tabellen kopieren.

Beispiel für das Archivieren

Als Beispiel dient wieder einmal die Nordwind-Datenbank: Hier sollen die Daten aus den miteinander verknüpften Tabellen Bestellungen und Bestelldetails archiviert werden. Außerdem sollen die Datensätze der Tabelle Artikel, die Auslaufartikel enthalten, deren Bestand 0 ist, archiviert werden. Auch diese werden für den laufenden Betrieb nicht mehr benötigt.

Archivieren per VBA

Die Archivierung kann nach verschiedenen Methoden durchgeführt werden, jedoch wird fast immer VBA im Spiel sein. Variabel ist der Einsatz der benötigten Aktionsabfragen: Diese können Sie wahlweise als gespeicherte Abfragen oder als SQL-Ausdrücke im VBA-Code anlegen.

Die Routine aus Quellcode 1 verwendet der besseren Übersichtlichkeit halber letztere Variante.

Eine weitere Frage stellt sich zur Organisation der Archivdatenbank. Soll dies eine Datenbank sein, an deren Tabellen die archivierten Daten angehängt werden, oder soll lieber für jeden Archivierungsvorgang eine neue Datenbank angelegt werden?

Wenn nicht nach wenigen Archivierungen bereits eine neue Datenbank angelegt werden muss, weil die vorherige Archivdatenbank annähernd zwei Gigabyte Daten enthält, sollten Sie die zu archivierenden Daten an die Tabellen einer einzigen Archivdatenbank anhängen.

Falls die Datenmenge sehr groß ist, erzeugen Sie besser jeweils eine neue Archivdatenbank. Im Beispiel kommt die Variante mit der Erstellung einer neuen Archivdatenbank zum Tragen.

Interessante Techniken

Die Archivierungsroutine aus Quellcode 1 offenbart einige Techniken, die bei den meisten Entwicklern nicht täglich zum Einsatz kommen dürften.

Erstellen einer neuen Datenbank

Die erste interessante Technik ist das Erstellen einer neuen Datenbank mit der CreateDatabase-Methode des DBEngine-Objekts. Die Methode erwartet zwei Parameter: den Pfad und Dateinamen der zu erstellenden Datenbank sowie eine Konstante, die die zu verwendende Sortierreihenfolge angibt. Die hier eingesetzte Konstante dbLangGeneral enthält die in Deutschland und einigen anderen Ländern übliche Sortierreihenfolge.

Der Dateiname der zu erstellenden Datei setzt sich aus dem Pfad der aktuellen Datenbank und dem aktuellen Datum im Format yyyymmdd plus der Dateiendung .mdb zusammen.

Die Routine prüft, ob die zu erstellende Archivdatenbank bereits vorhanden ist - dazu wird der beim Versuch, eine bestehende Datenbank zu überschreiben, ausgelöste Fehler behandelt.

Ist die Datenbank bereits vorhanden, wird der Benutzer gefragt, ob er die Datenbank überschreiben möchte.

Daten in andere Datenbank schreiben

Die noch leere Datenbank wird nun mit den zu archivierenden Daten gefüllt. Dazu verwendet die Routine die SELECT INTO-Anweisung, die eine neue Tabelle auf Basis der ausgewählten Felder und Daten anlegt.

Das Besondere an dieser Anweisung ist in diesem Fall, dass die Tabelle in einer externen Datenbank - in der soeben angelegten Datenbank - erstellt wird. Dazu geben Sie mit der IN-Klausel hinter dem Namen der zu erstellenden Tabelle die zu verwendende Zieldatenbank an.

Diese IN-Klausel ist im Übrigen nicht mit der für Unterabfragen verwendeten Variante zu verwechseln, die gleich ebenfalls zum Tragen kommt. Im vorliegenden Fall werden die Tabellen ohne Beziehungen einfach in die Archivtabelle kopiert. Daher ist die Reihenfolge beim Archivieren vernachlässigbar. Die drei SELECT INTO-Anweisungen erledigen folgende Schritte:

  • Kopieren aller Datensätze der Tabelle Bestellungen, deren Lieferdatum 60 oder mehr Tage zurückliegt
  • Kopieren aller zu diesen Bestellungen gehörenden Datensätze der Tabelle Bestelldetails
  • Quellcode 1: Archivieren von Daten in eine neue Datenbank

    Public Function Archivieren() As Boolean

        

        Dim db As DAO.Database

        Dim strPfad As String

        

        Set db = CurrentDb

        

        'Fehlerbehandlung aktivieren

        On Error Resume Next

        

        'Pfad der Archivdatenbank festlegen

        strPfad = CurrentProject.Path & "\" & Format(Date, "yyyymmdd") & ".mdb"

        

        'Archivdatenbank erstellen

        DBEngine.CreateDatabase strPfad, dbLangGeneral

        

        'Falls Datenbank schon vorhanden

        If Err = 3204 Then

            If MsgBox("Die Datenbank ist bereits vorhanden. Soll diese überschrieben werden?", _
                vbYesNo) = vbYes Then

                Kill strPfad

                If Err = 70 Then

                    MsgBox "Die Datenbank kann nicht gelöscht werden. Der Vorgang wird abgebrochen."

                    Exit Function

                End If

                DBEngine.CreateDatabase strPfad, dbLangGeneral

            Else

                Exit Function

            End If

        End If

        

        'Fehlerbehandlung deaktivieren

        On Error GoTo 0

        

        'Daten in neue Datenbank kopieren

        db.Execute "SELECT Bestellungen.* INTO Bestellungen IN '" & strPfad & "' FROM Bestellungen" _
            & " WHERE Lieferdatum <= " & Format(Date - 60, "\#yyyy\-mm\-dd\#"), dbFailOnError

        db.Execute "SELECT Bestelldetails.* INTO Bestelldetails IN '" & strPfad & "' FROM " _
            & "Bestelldetails INNER JOIN Bestellungen ON Bestelldetails.[Bestell-Nr] = " _
            & "Bestellungen.[Bestell-Nr] WHERE Bestellungen.Lieferdatum <= " & Format(Date - 60, _
            "\#yyyy\-mm\-dd\#"), dbFailOnError

        db.Execute "SELECT Artikel.* INTO Artikel IN '" & strPfad & "' FROM Artikel WHERE " _
            & "Auslaufartikel = TRUE AND Lagerbestand = 0 AND Artikel.[Artikel-Nr] NOT IN " _
            & "(SELECT DISTINCT Bestelldetails.[Artikel-Nr] FROM Bestelldetails)", dbFailOnError

        

        'Daten löschen

        db.Execute "DELETE Bestelldetails.* FROM Bestelldetails INNER JOIN Bestellungen ON " _
            & "Bestelldetails.[Bestell-Nr] = Bestellungen.[Bestell-Nr] WHERE " _
            & "Bestellungen.Lieferdatum <= " & Format(Date - 60, "\#yyyy\-mm\-dd\#"), dbFailOnError

        db.Execute "DELETE FROM Bestellungen WHERE Lieferdatum <= " & Format(Date - 60, _
            "\#yyyy\-mm\-dd\#"), dbFailOnError

        db.Execute "DELETE FROM Artikel WHERE Auslaufartikel = TRUE AND Lagerbestand = 0 " _
            & "AND Artikel.[Artikel-Nr] NOT IN (SELECT DISTINCT Bestelldetails.[Artikel-Nr] " _
            "FROM Bestelldetails)", dbFailOnError    

        Set db = Nothing

    End Function

  • Kopieren aller Artikel, die Auslaufartikel sind, deren Lagerbestand 0 ist und die in keiner nach dem Archivieren vorhandenen Bestellung mehr vorkommen
  • Wichtiger ist die Reihenfolge in den folgenden drei Anweisungen zum Löschen der archivierten Datensätze. Hier werden zunächst die Datensätze der Tabelle Bestelldetails gelöscht, die mit im folgenden Vorgang zu löschenden Datensätzen der Tabelle Bestellungen verknüpft sind.

    Das Löschen der ausgelaufenen Artikel erfolgt zuletzt: Die entsprechende DELETE-Anweisung löscht alle Datensätze, die ausgelaufen sind, die nicht mehr auf Lager sind und die mit keinem der noch vorhandenen Bestelldetails verknüpft sind.

    Die Routine zeigt nur beispielhaft, wie das Archivieren funktionieren kann. In der Tat sind noch Mechanismen zu integrieren, die vor dem Löschen prüfen, dass auch nur so viele Datensätze gelöscht werden, wie auch archiviert wurden.

    Der ausführliche Ablauf sieht dann folgendermaßen aus:

  • Archivieren der Datensätze
  • Zählen der archivierten Datensätze
  • Sicherung der betroffenen Tabellen
  • Löschen der archivierten Datensätze
  • Abgleich der Anzahl der archivierten mit der Anzahl der gelöschten Datensätze und gegebenenfalls Fehlermeldung
  • Quellcode 2: Wiederherstellen von Daten

    Public Function Wiederherstellen(strDateiname As String)

        Dim db As DAO.Database

        Set db = CurrentDb

        db.Execute "INSERT INTO Bestellungen SELECT * FROM Bestellungen IN '" & strDateiname & "'", _
            dbFailOnError

        db.Execute "INSERT INTO Artikel SELECT * FROM Artikel IN '" & strDateiname & "'", _
            dbFailOnError

        db.Execute "INSERT INTO Bestelldetails SELECT * FROM Bestelldetails IN '" & strDateiname _
            & "'", dbFailOnError

        Set db = Nothing

    End Function

    Wiederherstellen archivierter Daten

    Das Wiederherstellen der Daten ist weniger aufwändig, da hier nur die archivierten Daten wieder in die ursprünglichen Tabellen zurückkopiert werden müssen.

    Zu beachten ist hier insbesondere die Reihenfolge, denn im Gegensatz zur Archivdatenbank, deren Tabellen nicht zwingend miteinander verknüpft sind, sind für die Tabellen der Ausgangsdatenbank Verknüpfungen mit referentieller Integrität zwischen den Tabellen festgelegt.

    Wenn die wiederherzustellenden Daten sich nicht in einer einzigen Archivdatenbank befinden, müssen Sie die Daten außerdem in umgekehrter Reihenfolge wiederherstellen - das heißt, dass Sie zunächst die zuletzt archivierten Daten wiederherstellen und erst dann mit den älteren Daten fortfahren.

    Im Detail sieht dies für die zuvor archivierten Daten wie in Quellcode 2 aus. Die Funktion Wiederherstellen erwartet den Dateinamen der Archivdatenbank inklusive Pfad als Parameter.

    Probleme beim Wiederherstellen

    Wenn Sie genau die Daten wiederherstellen, die Sie auch archiviert haben, dürften theoretisch keine Probleme auftreten - bis auf eines. Wenn Sie zwischendurch die Originaldatenbank komprimieren, werden auch die Autowerte der einzelnen Tabellen initialisiert.

    Das wirkt sich dann unter folgenden Umständen hinderlich aus: Angenommen, das Primärschlüsselfeld der zehn Datensätze einer Tabelle enthält die Werte von 1 bis 10. Wenn Sie den letzten Datensatz archivieren und löschen, ist der höchste Primärschlüsselwert 9. Trotzdem legt Access beim Anlegen eines neuen Datensatz für das Primärschlüsselfeld den Wert 11 an - ein Wiederherstellen des Datensatzes mit der Nummer 10 wäre also kein Problem.

    Wenn Sie Access mit einer Jet-Version älter als Jet 4.0 Service Pack 4 verwenden, kann es aber zu folgendem Problem kommen: Das Komprimieren der Datenbank führt in dieser Konstellation dazu, dass der Zähler für den Primärschlüssel initialisiert wird.

    Dadurch erhält ein neuer Datensatz wiederum den Primärschlüsselwert 10 - welcher dann zusammen mit dem archivierten Datensatz zweimal vorhanden ist.

    Ein Wiederherstellen des archivierten Datensatzes ist unter diesen Bedingungen natürlich nicht möglich.

    Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

    Sind Sie Abonnent?Jetzt einloggen ...
     

    Kompletten Artikel lesen?

    Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

    E-Mail:

    Verwandte Beiträge:

    SQL-Datenbankschema auslesen

    Datenbanken und Tabellen per SQL anpassen

    © 2003-2015 André Minhorst Alle Rechte vorbehalten.