Ziel: Wissen, wer wann was geändert hat

Access speichert keine Historie.
Wenn ein Wert überschrieben wird, ist der alte weg.
Du willst: nachvollziehen, wer was wann geändert hat – und was vorher drinstand.

Geht. Mit Bordmitteln und etwas Disziplin.

Variante 1: Änderungsprotokoll in einer eigenen Tabelle

Tabelle tblAudit

  • ID (Autowert)
  • Tabelle
  • Feld
  • DatensatzID
  • AlterWert
  • NeuerWert
  • GeändertAm
  • Benutzer

Funktion zum Protokollieren

Public Sub LogÄnderung(tabelle As String, feld As String, datensatzID As Long, alt As Variant, neu As Variant)
    If Nz(alt, "") <> Nz(neu, "") Then
        CurrentDb.Execute "INSERT INTO tblAudit (Tabelle, Feld, DatensatzID, AlterWert, NeuerWert, GeändertAm, Benutzer) " & _
                          "VALUES ('" & tabelle & "', '" & feld & "', " & datensatzID & ", '" & Replace(alt, "'", "''") & "', '" & Replace(neu, "'", "''") & "', Now(), '" & Environ("USERNAME") & "')"
    End If
End Sub

Anwendung im Formular

Private Sub txtFirma_BeforeUpdate(Cancel As Integer)
    Call LogÄnderung("tblKunden", "Firma", Me.ID, Me.txtFirma.OldValue, Me.txtFirma.Value)
End Sub

Nur Werte, die sich wirklich ändern, werden geloggt.

Variante 2: Komplettprotokoll auf Formular-Ebene

Wenn Du viele Felder hast:

Private Sub Form_BeforeUpdate(Cancel As Integer)
    Call LogÄnderung("tblKunden", "Name", Me.ID, Me.txtName.OldValue, Me.txtName.Value)
    Call LogÄnderung("tblKunden", "PLZ", Me.ID, Me.txtPLZ.OldValue, Me.txtPLZ.Value)
    ' usw.
End Sub

Oder: Schleife über alle Felder, wenn Du’s generisch willst.

Variante 3: Tabellenweise Triggerlogik mit Zeitstempel

Jede Tabelle bekommt:

  • GeändertAm
  • GeändertVon

Im Formular:

Private Sub Form_BeforeUpdate(Cancel As Integer)
    Me.GeändertAm = Now()
    Me.GeändertVon = Environ("USERNAME")
End Sub

Einfach. Schnell. Zeigt Dir zumindest, dass jemand was gemacht hat.

Variante 4: Tabelle duplizieren für „Versionen“

Du willst alte Stände aufbewahren? Dann brauchst Du:

Tabelle tblKunden_Historie

Gleich aufgebaut wie tblKunden, nur mit zusätzlichem Feld VersionDatum.

Bei jeder Änderung:

CurrentDb.Execute "INSERT INTO tblKunden_Historie SELECT *, Now() FROM tblKunden WHERE ID = " & Me.ID

Dann den echten Datensatz aktualisieren.

Nachteil: Speicherverbrauch
Vorteil: vollständige Historie

Variante 5: Automatische ID-Tracking-Lösung (nur Insert)

Wenn Du nur wissen willst, wer was angelegt hat:

Private Sub Form_BeforeInsert(Cancel As Integer)
    Me.ErstelltAm = Now()
    Me.ErstelltVon = Environ("USERNAME")
End Sub

Reicht für viele KMU-Prozesse schon aus.

Tipps für saubere Protokolle

  • Benutzername immer per Environ("USERNAME")
  • Änderungsdatum immer mitloggen
  • Freitext-Felder mit Replace(..., "'", "''") absichern
  • Felder mit Format (Währung, Datum, Checkbox) explizit umwandeln
  • Audit-Funktionen zentral halten – nicht pro Formular wild einbauen

Einsatzszenarien

  • Kundenakten nachverfolgen
  • Änderungen an Preisen, Rabatten oder Zahlungszielen
  • Revisionspflichtige Daten (z. B. HR, Medizin, Finanzen)
  • Interne Freigabestrecken
  • Fehleranalysen („Wer hat’s geändert?“)

Fazit für Entwickler

Access kann keine Trigger – aber mit ein bisschen Struktur bekommst Du trotzdem eine nachvollziehbare Änderungsverfolgung hin.

Und: SQL Server ist beim Auditieren um Längen überlegen.

Ich erklär Dir kurz beides – ohne Geschwafel.

Warum Access keine Trigger hat

Ein Trigger ist in SQL ein Datenbankobjekt, das automatisch bei bestimmten Ereignissen feuert – etwa bei INSERT, UPDATE, DELETE.

Access (bzw. die Jet/ACE-Engine) unterstützt keine Trigger auf Tabellenebene.

Was Access kennt, sind:

  • Formular-Ereignisse (BeforeUpdate, AfterUpdate usw.)
  • Makros (ja, die gibt’s auch als „Datenmakros“ in Access Web-Apps – aber das ist veraltet und praktisch tot)

Das heißt:
Wenn Du Änderungen in Access nachverfolgen willst, musst Du das im Frontend (VBA) selbst tun.

Wenn jemand aber per ODBC, Abfrage oder Code auf die Tabelle zugreift und dort ändert – ist nix mit „BeforeUpdate“. Access merkt davon nichts.

Warum Trigger + Audit mit SQL Server besser sind

Wenn Du Dein Access-Frontend mit einem SQL Server-Backend kombinierst, kannst Du dort echte Trigger definieren.
Die laufen immer, egal ob jemand per Access, Power BI, Excel, .NET, Python oder sonst was auf die Tabelle schreibt.

Beispiel: SQL Server-Trigger auf Änderung

CREATE TRIGGER trg_Kunden_Audit
ON dbo.Kunden
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO dbo.Kunden_Audit (KundenID, Feld, AlterWert, NeuerWert, GeändertAm, GeändertVon)
    SELECT
        i.ID,
        'Name',
        d.Name,
        i.Name,
        GETDATE(),
        SYSTEM_USER
    FROM inserted i
    JOIN deleted d ON i.ID = d.ID
    WHERE i.Name <> d.Name
END

Vorteile:

  • zentral
  • unabhängig vom Access-Frontend
  • läuft immer, auch bei Batch-Imports
  • keine VBA-Pflege nötig
  • automatisierbar und analysierbar per SQL

Weitere Stärken:

  • Versionsverwaltung per „Change Tracking“ oder „Temporal Tables“
  • Logging auch für Löschungen
  • kombinierbar mit Security-Kontexten (SYSTEM_USER, SUSER_SNAME())
  • Exportierbar für Prüfungen, Revisionssicherheit, DSGVO-Dokumentation

  • Access? Nur Frontend-Ereignisse. Keine echten Trigger.
  • Wenn’s ordentlich, zentral und verlässlich sein soll: SQL Server
  • Für KMU mit Compliance- oder Protokollanforderung: SQL Server + Trigger = Pflicht

Tags:

No responses yet

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert