Wer hat den Wert geändert? Eine revisionssichere Änderungshistorie für Access-Anwendungen

Der Prüfer zeigt auf einen Messwert in der Qualitätsdatenbank und fragt: „Wer hat den von 12,4 auf 12,7 geändert, und wann?“ Im Raum wird es still. Die Anwendung läuft seit über zehn Jahren, das Frontend ist Microsoft Access, irgendwann sind die Tabellen in den SQL Server gewandert. Eine revisionssichere Änderungshistorie hat nie jemand eingebaut. Also lautet die Antwort: „Das wissen wir nicht.“ Genau diese Antwort macht ein IATF-16949- oder ISO-9001-Audit teuer. Bei Produkthaftung wird aus der Lücke ein echtes Risiko.

Die gute Nachricht: Wenn deine Tabellen bereits im SQL Server liegen, ist das Problem in einem halben Tag gelöst. Ohne neues ERP, ohne das funktionierende Access-Frontend anzufassen.

Das Access-Frontend ist nicht das Problem. Das Backend entscheidet.

Der erste Reflex lautet meist: „Access ist eben nicht audit-sicher.“ Das ist die falsche Diagnose. Ob eine Änderung beweisbar ist, entscheidet nicht die Maske, in die jemand tippt. Es entscheidet die Stelle, an der die Daten liegen.

Liegt das Backend als .accdb auf einer Freigabe, ist es eine Datei. Jeder mit dem Pfad öffnet sie und ändert jeden Wert, an deiner Anwendung vorbei, ohne Spur. Eine selbstgebaute Logtabelle hilft da nicht: Sie wird nur gefüllt, wenn die Änderung durch dein Formular läuft. Direkte Tabellenedits, Importe und Fremdtools sieht sie nicht. Genau diesen Zustand will ein Auditor aufdecken, und er findet ihn.

Liegt das Backend dagegen im SQL Server, kannst du die Beweisbarkeit auf Datenbankebene erzwingen, unabhängig davon, wer oder was schreibt. Das Access-Frontend bleibt unverändert, die verknüpften Tabellen sehen weiter aus wie immer. Aus meiner Praxis im norddeutschen Mittelstand ist das der häufigste Fall: Das Backend ist längst auf dem SQL Server, aber es sind nur „einfache“ Tabellen, kein Trigger, keine Prozedur, keine Historie. Die halbe Miete ist bezahlt, die zweite Hälfte fehlt.

Eine revisionssichere Änderungshistorie gibt es nur im Backend, nicht im Frontend

Seit SQL Server 2016 gibt es dafür das passende Werkzeug, und zwar in jeder Edition bis hinunter zur kostenlosen Express Edition: System-Versioned Temporal Tables.

System-Versioned Temporal Tables sind Tabellen, bei denen SQL Server jede frühere Zeilenversion automatisch in einer geschützten History-Tabelle mit Gültigkeitszeitraum ablegt. Du brauchst dafür keinen Anwendungscode, keinen Trigger und keine Disziplin der Benutzer. Jedes UPDATE und jedes DELETE schreibt die alte Version selbsttätig in die Historie, mit Start- und End-Zeitstempel.

Der entscheidende Unterschied zur selbstgebauten Logtabelle: Solange die Versionierung aktiv ist, kann niemand die History-Tabelle direkt überschreiben, auch die Anwendung nicht. Wer die Vergangenheit fälschen will, muss die Versionierung erst abschalten. Das ist ein Eingriff mit Administratorrechten und selbst ein protokollierbares Ereignis. Eine Logtabelle, die jeder Schreiber per UPDATE frisieren konnte, hatte diesen Schutz nie.

Der Haken: Temporal Tables sagen „was“ und „wann“, aber nicht „wer“

Das ist der Punkt, den die meisten „Nimm einfach Temporal Tables“-Anleitungen verschweigen, und der bei einer Audit-Frage zuerst auffällt.

Temporal Tables beantworten lückenlos, was wann von welchem Wert auf welchen geändert wurde. Wer es war, beantworten sie nicht. Die Periodenspalten enthalten nur Zeit, keine Identität. Für die „Wer“-Frage brauchst du eine zusätzliche, mitversionierte Spalte, die den Benutzer festhält.

Wie gut das funktioniert, hängt an der Anmeldung. Meldet sich deine Access-Anwendung mit Windows-Authentifizierung pro Benutzer an, ist die Identität sauber greifbar. Hängt dagegen die ganze Anwendung an einem gemeinsamen SQL-Login, kennt der Server nur dieses eine Konto, und die „Wer“-Frage bleibt offen, bis du den echten Benutzer beim Verbindungsaufbau mitgibst. Für audit-relevante Daten ist Windows-Authentifizierung pro Benutzer deshalb keine Geschmacksfrage, sondern Voraussetzung.

Für Entwickler: so rüstest du es nach

Ab hier wird es technisch. Wenn dich nicht der Code, sondern die wirtschaftliche Seite interessiert, springe zum Abschnitt „Was das fürs Geschäft heißt“.

Ausgangslage: Die Tabelle tblTabelle liegt bereits gefüllt im SQL Server, das Frontend ist Access mit verknüpften Tabellen, Anmeldung per Windows-Authentifizierung. Drei Schritte, einzeln pro Tabelle.

Zuerst die Identitätsspalte. ORIGINAL_LOGIN() ist SUSER_SNAME() vorzuziehen, weil es ein EXECUTE AS übersteht und damit den tatsächlichen Benutzer liefert.

ALTER TABLE dbo.tblTabelle ADD
    strTabGeaendertVon VARCHAR(128) NOT NULL
        CONSTRAINT dfTabGeaendertVon DEFAULT ORIGINAL_LOGIN();

Dann die beiden Periodenspalten und die Periode selbst. Bei einer bereits gefüllten Tabelle brauchen sie zwingend Default-Werte, sonst lehnt SQL Server das ADD ab.

ALTER TABLE dbo.tblTabelle ADD
      dtmTabGueltigVon DATETIME2(7) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL
        CONSTRAINT dfTabGueltigVon DEFAULT DATEADD(SECOND, -1, SYSUTCDATETIME())
    , dtmTabGueltigBis DATETIME2(7) GENERATED ALWAYS AS ROW END   HIDDEN NOT NULL
        CONSTRAINT dfTabGueltigBis DEFAULT CONVERT(DATETIME2(7), '9999-12-31 23:59:59.9999999')
    , PERIOD FOR SYSTEM_TIME (dtmTabGueltigVon, dtmTabGueltigBis);

Zum Schluss die Versionierung scharf schalten. Die History-Tabelle legt SQL Server automatisch an.

ALTER TABLE dbo.tblTabelle
    SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.tblTabelleHistory));

Das HIDDEN an den Periodenspalten ist bei einem Access-Frontend nicht optional, sondern der Knackpunkt. Ohne HIDDEN tauchen beide Spalten in jedem SELECT * und damit in jeder verknüpften Access-Tabelle auf. Gebundene Formulare, vorhandene Recordsets und jedes INSERT INTO tbl SELECT * brechen dann. Mit HIDDEN bleiben die Spalten unsichtbar, bis du sie ausdrücklich benennst. Nach der Umstellung die Tabellen in Access einmal neu verknüpfen, damit das gespeicherte Schema zur Datenbank passt.

Jetzt fehlt noch das „Wer“ beim UPDATE. Der Default greift nur beim INSERT. Beim UPDATE musst du die Identitätsspalte aktiv setzen. Am robustesten für ein Produkt mit vielen Formularen ist ein schlanker AFTER-Trigger, der serverseitig stempelt, egal über welches Formular die Änderung kommt.

CREATE OR ALTER TRIGGER dbo.trgTabelleUpd
ON dbo.tblTabelle
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE t
        SET t.strTabGeaendertVon = ORIGINAL_LOGIN()
    FROM dbo.tblTabelle AS t
    INNER JOIN inserted AS i
        ON i.idTabelle = t.idTabelle;
END;
GO

Ehrlicher Hinweis: Dieser Trigger fasst die Zeile ein zweites Mal an und erzeugt damit eine zusätzliche History-Version. Fürs Audit ist das unschädlich, die Zuordnung bleibt korrekt, nur die Historie wird etwas geschwätziger. Sauberer ist, die Identitätsspalte in derselben UPDATE-Anweisung zu setzen. Bei einem gewachsenen Produkt mit Dutzenden gebundenen Formularen ist der Trigger der pragmatische Weg, bei Neuentwicklung der saubere. Beachte außerdem: INSTEAD OF-Trigger sind auf system-versionierten Tabellen nicht erlaubt, nur AFTER.

Abgefragt wird die Historie über die FOR SYSTEM_TIME-Klausel. Für den Stand zu einem Stichtag, etwa dem Prüfungsdatum:

SELECT
     idTabelle
    ,dblTabMesswert
    ,strTabGeaendertVon
FROM dbo.tblTabelle
FOR SYSTEM_TIME AS OF '2026-01-15T10:00:00'
WHERE idTabelle = 4711;

Für die komplette Änderungskette einer einzelnen Zeile, also genau die Antwort auf die Prüferfrage:

SELECT
     dblTabMesswert
    ,strTabGeaendertVon
    ,dtmTabGueltigVon
    ,dtmTabGueltigBis
FROM dbo.tblTabelle
FOR SYSTEM_TIME ALL
WHERE idTabelle = 4711
ORDER BY dtmTabGueltigVon;

Das Ergebnis zeigt Zeile für Zeile, welcher Benutzer den Messwert wann von welchem auf welchen Wert gesetzt hat. Die normale verknüpfte Tabelle in Access zeigt davon nichts und liefert weiter nur den aktuellen Stand. Für die Historie baust du eine View oder eine Pass-Through-Abfrage, sodass die Formulare unverändert bleiben.

Ausblick: die anderen Audit-Funktionen des SQL Servers

Temporal Tables sind für „wer hat welchen Wert geändert“ das richtige Werkzeug, aber nicht das einzige. SQL Server Audit protokolliert auf Server- und Datenbankebene, wer sich anmeldet, Rechte ändert oder Strukturen anfasst, und ergänzt damit die fachliche Datenhistorie um die technische. Change Data Capture und Change Tracking zielen auf Synchronisation und ETL, nicht auf Revisionssicherheit. Und ab SQL Server 2022 gibt es mit Ledger eine kryptografisch manipulationssichere Variante für Fälle mit höchsten Nachweisanforderungen. Für die typische IATF- oder ISO-Frage im Mittelstand reichen Temporal Tables plus eine Identitätsspalte aus. Das Übrige ist Verstärkung, kein Pflichtprogramm.

Wo der Ansatz an Grenzen stößt

Drei ehrliche Einschränkungen. Erstens: Einen Administrator mit sysadmin-Rechten hält auch die Versionierung nicht auf. Er kann sie abschalten, Daten ändern und wieder einschalten. Temporal Tables heben die Latte deutlich, sie machen Manipulation nicht unmöglich. Zweitens: Audit-relevant ist nie die ganze Tabelle, sondern ein paar konkrete Felder, Messwerte, QM-Freigaben, Statuswechsel. Temporal Tables versionieren immer die komplette Zeile. Breite Tabellen mit langen Bemerkungsfeldern blähen die Historie auf, über viele Installationen multipliziert sich das. Erst die Felder bestimmen, welche Tabellen wirklich temporal werden müssen. Struktur vor Tool, auch hier. Drittens, der entscheidende Vorbehalt: Das alles setzt voraus, dass das Backend im SQL Server liegt. Steckt es noch als .accdb auf einer Freigabe, führt kein Weg an der Migration vorbei. Audit-Sicherheit auf einer Datei gibt es nicht.

Was das fürs Geschäft heißt

Für den Geschäftsführer ist der Kern simpel: Beim nächsten Audit lautet die Antwort auf „Wer hat das geändert?“ nicht mehr „Das wissen wir nicht“, sondern eine Abfrage, die Benutzer, Zeitpunkt und alten Wert auf den Tisch legt. Das schließt eine Lücke, die im Haftungsfall richtig teuer werden kann.

Genauso wichtig ist, was nicht passiert: Es braucht dafür kein neues ERP und keinen Abschied vom funktionierenden Access-Frontend. Die Datenbank, die ohnehin schon im SQL Server liegt, wird ertüchtigt, der Rest bleibt. Wer schon ein Angebot für ein audit-fähiges Fremdsystem auf dem Tisch hatte, sieht hier die deutlich günstigere Alternative.

Wenn du eine gewachsene Access-Anwendung mit SQL-Server-Backend hast und vor der nächsten Prüfung wissen willst, ob deine Daten beweisbar sind, schau es dir an oder lass es dir anschauen. Erreichbar bin ich über sesoft.de/kontakt, ein kostenloses Erstgespräch geht über sesoft.de/kostenloses-erstgespraech-sichern.

Quellen

Über den Autor

Sönke Schäfer ist selbstständiger Datenarchitekt aus Sierksdorf und berät seit über 25 Jahren norddeutsche Mittelständler rund um Microsoft Access, VBA und SQL Server. Sein Schwerpunkt liegt darauf, gewachsene Anwendungen pragmatisch zu ertüchtigen, statt sie reflexhaft zu ersetzen, hier am Beispiel einer revisionssicheren Änderungshistorie für ein Audit. Mehr über Sönke Schäfer

Nach oben scrollen