Timestamp-Felder in Access nachbilden

01.01.2007 von Helma  Spona
Timestamp-Felder sind besondere Felder in MySQL und anderen Datenbankservern. Sie werden wie die AutoWert-Felder von Access vom Datenbankserver mit dem aktuellen Datum und der aktuellen Uhrzeit gefüllt, die zur Datensatzerstellung oder letzten Änderung gültig waren. Und gerade dafür sind diese Felder sehr nützlich, weil sich jederzeit nachvollziehen lässt, wann die letzte Änderung erfolgt ist.

Dass es Timestamp-Felder in Access nicht gibt, heißt aber nicht, dass Sie auf deren Annehmlichkeiten verzichten müssen. Dieser Beitrag zeigt Ihnen, wie Sie solche Felder in Access nachbilden.

Datumsfelder als Basis

Wenn Sie immer das aktuelle Datum speichern möchten, wenn sich der Datensatz geändert hat, benötigen Sie in jeder Tabelle, die ein Timestamp-Feld enthalten soll, ein Datumsfeld. Als Standardwert für das Datumsfeld geben Sie =Jetzt() ein (Bild 1). Das führt dazu, dass alle neuen Datensätze automatisch das aktuelle Datum und die aktuelle Uhrzeit im Feld enthalten. Benötigen Sie das Timestamp-Feld in mehreren Tabellen, sollten Sie dieses Feld einheitlich benennen. Das macht die weitere Verarbeitung des Feldes in den Tabellen einfacher, weil Sie dann in allen Tabellen anhand des Feldnamens erkennen können, dass es sich um das Timestamp-Feld handelt.

Bild 1: Einstellungen für das Datumsfeld.

Den Feldwert beim Speichern setzen

Damit ist allerdings noch nicht das Problem gelöst, dass sich der Feldwert bei einer Änderung des Datensatzes nicht ändert. Das ist also noch zu erledigen. Normalerweise werden zum Ändern von Datensätzen in Access Formulare verwendet. Sie können daher die entsprechenden Formularereignisse nutzen.

Grundlage dafür ist ein Formular, das auf der Tabelle mit dem Timestamp-Feld basiert. Für dieses Formular erzeugen Sie dann eine Ereignisprozedur für das zu verwendende Ereignis. Nutzen lassen sich dafür mehrere Ereignisse. Am einfachsten ist die Nutzung des Dirty-Ereignisses (Bei Geändert). Es steht allerdings in Access 97 nicht zur Verfügung.

Private Sub Form_Dirty(Cancel As Integer)
Me.Timestamp.Value = Now
End Sub

Möchten Sie das Dirty-Ereignis nutzen, weisen Sie in dessen Ereignisprozedur einfach dem Timestamp-Feld das Ergebnis der Now-Funktion zu. Da das Ereignis in Access 97 noch nicht zur Verfügung steht, müssen Sie hier einen anderen Weg gehen. Für jedes Steuerelement des Formulars, das zur Eingabe und Änderung der Daten dient, erstellen Sie eine Ereignisprozedur für das Change-Ereignis (Bei Änderung). Dort fügen Sie dann ebenfalls die Anweisung Me.Timestamp.Value =Now ein (Listing 2).

Private Sub ID_Change()
Me.Timestamp.Value = Now
End Sub

Prüfen, ob Feldwerte tatsächlich geändert wurden

Das funktioniert zwar, hat allerdings einen Haken: Ändert der Benutzer einen Feldwert durch Eingabe oder Auswahl eines Listeneintrags und stellt danach wieder den alten Wert ein, tritt dennoch das Ereignis ein und das Timestamp-Feld wird geändert.

Das ist jedoch nicht exakt das Verhalten, das beispielsweise MySQL aufweist. Dort erkennt der Datenbankserver, ob bei einer UPDATE-Anweisung wirklich Feldwerte geändert wurden. Nur in diesem Fall wird das Timestamp-Feld geändert. Möchten Sie dieses Verhalten nachbilden, ist etwas mehr Aufwand erforderlich.

Sie müssen vor der Änderung des Timestamp-Feldes prüfen, ob mindestens ein Wert von dem alten Wert abweicht. Das ist im Prinzip kein Problem, weil in der Eigenschaft OldValue eines jeden Formularfeldes auch der ursprüngliche Feldwert gespeichert ist. Sie müssen also nur alle Steuerelemente des Formulars durchlaufen und prüfen, ob deren Eigenschaftswert für die Eigenschaft OldValue von dem der Value-Eigenschaft abweicht.

Es ist also eine Funktion zu erstellen, der alle Felder übergeben werden und die dann für jedes Feld prüft, ob es geändert wurde. Falls ja, weisen Sie dem Rückgabewert True zu, ansonsten behält die Funktion den Rückgabewert False, der am Anfang gesetzt wurde (Listing 3).

Function boolGeaendert(ParamArray objContr() As Variant) As Boolean
Dim objC As Variant
Dim objContr2 As Control
boolGeaendert = False
For Each objC In objContr
Set objContr2 = objC
If objContr2.Value <> objContr2.OldValue Then
boolGeaendert = True
Exit For
End If
Next objC
End Function

Aufruf der Testfunktion

Diese Funktion müssen Sie jetzt natürlich aufrufen. In den bisher genutzten Ereignissen geht das nicht, weil das Change-Ereignis ja auch eintritt, wenn der Benutzer den alten Wert des Feldes wiederherstellt. Das würde dazu führen, dass das Timestamp-Feld schon geändert wird, bevor der Benutzer die Eingabe rückgängig machen kann.

Sie müssen sich also mit einem Ereignis behelfen, das erst eintritt, bevor die Daten in die Datenbank geschrieben werden. Passend ist dafür das Ereignis BeforeUpdate (Vor Aktualisierung) des Formulars. In der Ereignisprozedur für dieses Ereignis rufen Sie die Funktion boolGeaendert auf und übergeben ihr alle Steuerelemente, die Daten enthalten, als Parameterarray. Liefert die Funktion True zurück, setzen Sie das Timestamp-Feld. (hs/mha)

Private Sub Form_BeforeUpdate(Cancel As Integer)
If boolGeaendert(Me.Nachname, Me.Vorname, Me.ID) Then
Me.Timestamp.Value = Now
End If
End Sub

Helma Spona <hs> studierte Wirtschaftswissenschaft mit Schwerpunkt Betriebsinformatik und eröffnete nach Abschluss ihres Studiums 1996 eine EDV-Beratung in Kerken, die sich auf Datenbankentwicklung und Webdesign spezialisiert hat. Außerdem schreibt sie regelmäßig Beiträge für verschiedene Zeitschriften sowie Bücher zu Programmier- und Datenbankthemen. Sie können sie über ihre Website erreichen.