SQL Server Audit-Trigger: Änderungen sauber protokollieren
TL;DR — Ein DML-Trigger mit INSERTED und DELETED protokolliert zuverlässig, wer wann welchen Wert geändert hat. Die drei Fallen, an denen die meisten Umsetzungen scheitern: der Trigger feuert einmal pro Statement, nicht pro Zeile; er läuft in derselben Transaktion wie die Änderung; und TRUNCATE TABLE löst ihn gar nicht aus. Für reine Historie gibt es seit SQL Server 2016 mit Temporal Tables den bequemeren Weg — nur beantwortet der nicht die Frage nach dem Wer.
Warum die Tabelle selbst die Frage nicht beantwortet
Eine Zeile in der Datenbank kennt nur ihren aktuellen Zustand. Steht dort ein Kreditlimit von 50.000, weiß niemand, ob es gestern noch 5.000 waren, wer es geändert hat und ob das Absicht war. Genau diese Frage stellt aber jede Revision, jeder Support-Fall und jede Ursachensuche nach einem Datenfehler.
Ein UPDATE-Protokoll in der Anwendung hilft nur, solange alle Schreibzugriffe durch die Anwendung laufen. Sobald jemand per Management Studio, Importskript oder Reporting-Werkzeug direkt auf die Tabelle schreibt, ist die Lücke da — und das sind erfahrungsgemäß genau die Änderungen, nach denen später gesucht wird. Ein Trigger sitzt dagegen an der Tabelle und sieht jeden Weg.
Typische Anwendungsfälle
- Stammdaten mit Geldbezug — Kreditlimits, Rabattsätze, Zahlungsziele
- Berechtigungen — wer hat wem welche Rolle gegeben
- Preise und Konditionen — nachvollziehen, ab wann welcher Preis galt
- Statuswechsel — Auftrag storniert, Konto gesperrt, Vertrag beendet
- Fehlersuche — welcher Lauf hat die 4.000 Zeilen überschrieben
- Nachweispflichten — Aufbewahrung von Änderungshistorien über die Dauer der jeweiligen gesetzlichen oder vertraglichen Frist (siehe den Abschnitt zur Aufbewahrung)
Der Trigger, Schritt für Schritt
Die Beispiele gehören auf ein Testsystem, bevor sie an einer produktiven Tabelle hängen — ein Trigger greift in jede schreibende Transaktion ein, und ein Fehler darin legt sie mit lahm.
Zuerst die Protokolltabelle. Sie hält alten und neuen Wert, den Zeitpunkt, den Verursacher und die Art der Änderung:
CREATE TABLE dbo.kunde_audit (
audit_id BIGINT IDENTITY(1,1) PRIMARY KEY
, kunde_id INT NOT NULL
, aktion CHAR(6) NOT NULL -- INSERT, UPDATE, DELETE
, spalte SYSNAME NULL
, wert_alt NVARCHAR(4000) NULL
, wert_neu NVARCHAR(4000) NULL
, geaendert_am DATETIME2(3) NOT NULL CONSTRAINT DF_kunde_audit_am DEFAULT SYSUTCDATETIME()
, geaendert_von SYSNAME NOT NULL
, anwendung NVARCHAR(128) NULL
);
SYSUTCDATETIME() statt GETDATE(): ein Protokoll, das über eine Zeitumstellung läuft, wird sonst mehrdeutig — im Oktober gibt es zwei Stunden mit derselben Ortszeit. Warum Zeitzonen und Formate in SQL so verlässlich Ärger machen, steht ausführlich in unserem Beitrag zum SQL-Datumsformat.
Der Verursacher wird im Trigger gesetzt, nicht als Vorgabewert der Spalte. Das ist Absicht: So lässt sich der von der Anwendung mitgegebene Benutzer bevorzugen und erst dann auf den Anmeldenamen zurückfallen (siehe unten), und der Wert steht auch dann, wenn jemand die Protokolltabelle einmal direkt befüllt.
ORIGINAL_LOGIN() statt SUSER_SNAME(): Nach einem EXECUTE AS liefert SUSER_SNAME() den angenommenen Kontext, ORIGINAL_LOGIN() den tatsächlichen Anmeldenamen. Für ein Protokoll ist letzterer die interessante Angabe.
Der Trigger selbst:
CREATE OR ALTER gibt es ab SQL Server 2016 SP1; auf älteren Ständen wird daraus ein CREATE TRIGGER mit vorherigem DROP.
CREATE OR ALTER TRIGGER dbo.TR_kunde_audit
ON dbo.kunde
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM inserted) AND NOT EXISTS (SELECT 1 FROM deleted)
RETURN; -- UPDATE, das keine Zeile getroffen hat
INSERT INTO dbo.kunde_audit (kunde_id, aktion, spalte, wert_alt, wert_neu, geaendert_von, anwendung)
SELECT COALESCE(i.kunde_id, d.kunde_id)
, CASE WHEN i.kunde_id IS NULL THEN 'DELETE'
WHEN d.kunde_id IS NULL THEN 'INSERT'
ELSE 'UPDATE' END
, 'kreditlimit'
, CONVERT(NVARCHAR(4000), d.kreditlimit)
, CONVERT(NVARCHAR(4000), i.kreditlimit)
, COALESCE(CONVERT(SYSNAME, SESSION_CONTEXT(N'benutzer')), ORIGINAL_LOGIN())
, APP_NAME()
FROM inserted i
FULL OUTER JOIN deleted d ON i.kunde_id = d.kunde_id
WHERE i.kunde_id IS NULL -- DELETE: immer protokollieren
OR d.kunde_id IS NULL -- INSERT: immer protokollieren
OR NOT EXISTS (SELECT i.kreditlimit INTERSECT SELECT d.kreditlimit);
END;
Dieses Beispiel protokolliert eine Spalte, kreditlimit. Das ist der Normalfall in der Praxis: Man protokolliert die Felder, auf die es ankommt, nicht die ganze Tabelle. Für weitere Spalten wird der SELECT-Zweig wiederholt und per UNION ALL angehängt — ein generischer Trigger, der alle Spalten über Metadaten durchläuft, braucht dynamisches SQL und handelt sich dessen Nachteile ein.
Drei Stellen verdienen einen zweiten Blick.
SET NOCOUNT ON unterdrückt die zusätzliche Rückmeldung über betroffene Zeilen. Ohne sie bekommen manche Datenzugriffsschichten zwei Ergebnisse zurück und melden einen Fehler, obwohl das UPDATE erfolgreich war.
Der FULL OUTER JOIN deckt alle drei Aktionen mit einer Anweisung ab: Bei INSERT ist deleted leer, bei DELETE ist inserted leer, bei UPDATE sind beide gefüllt.
Die WHERE-Bedingung hat drei Teile, und alle drei werden gebraucht. Der INTERSECT-Vergleich ist null-sicher: ein simples WHERE i.kreditlimit <> d.kreditlimit übersieht jede Änderung, an der NULL beteiligt ist — der Vergleich ergibt dann UNKNOWN, und die Zeile fällt aus dem Protokoll. Genau diese stille Lücke ist der häufigste Fehler in Audit-Triggern.
Die beiden Vorbedingungen davor fangen die Kehrseite ab. INTERSECT behandelt NULL und NULL als gleich — bei einem INSERT ist die deleted-Seite leer, also NULL, und wenn der eingefügte Wert ebenfalls NULL ist, gälte die Zeile als unverändert und würde nicht protokolliert. Dasselbe beim Löschen einer Zeile, deren Wert NULL war. Deshalb: Ist eine der beiden Seiten gar nicht vorhanden, wird immer geschrieben, und der Wertvergleich entscheidet nur beim echten UPDATE.
Die Fallstricke, die den Unterschied machen
Der Trigger feuert einmal pro Anweisung, nicht pro Zeile. Das ist der Fallstrick, an dem die meisten Umsetzungen scheitern, und er ist heimtückisch, weil er im Test nie auffällt: Bei einer einzeln geänderten Zeile verhält sich ein falsch gebauter Trigger genau richtig. Ein UPDATE über 4.000 Zeilen ruft ihn trotzdem nur einmal auf, und inserted sowie deleted halten dann alle 4.000 Zeilen gleichzeitig. Wer an dieser Stelle mit Variablen arbeitet — SELECT @wert = spalte FROM inserted —, bekommt einen beliebigen Wert aus der Menge und protokolliert die übrigen 3.999 Änderungen überhaupt nicht. Deshalb schreibt der Trigger oben mengenbasiert: ein INSERT … SELECT über den Join, keine Schleife, keine Variablen.
Der Trigger läuft in derselben Transaktion. Wird die Änderung zurückgerollt, verschwindet auch der Protokolleintrag. Das ist meistens richtig so — ein Protokoll über eine Änderung, die nie stattgefunden hat, wäre falsch. Es bedeutet aber: Für ein Protokoll, das auch Fehlversuche festhalten soll, ist ein Trigger das falsche Werkzeug.
Ein Fehler im Trigger rollt alles zurück. Läuft die Protokolltabelle voll oder verletzt der Eintrag eine Bedingung, scheitert das ursprüngliche UPDATE mit. Die Protokolltabelle sollte deshalb so einfach wie möglich sein: keine Fremdschlüssel, keine Prüfbedingungen, kein Trigger auf ihr.
TRUNCATE TABLE feuert keinen Trigger. Es ist eine Metadaten-Operation und protokolliert die Zeilen nicht einzeln. Wer sich auf die Vollständigkeit des Protokolls verlässt, muss TRUNCATE per Berechtigung ausschließen. Dafür genügt es nicht, das Löschrecht zu entziehen: TRUNCATE hängt am ALTER TABLE-Recht, und genau das muss eingeschränkt werden.
Massenimporte umgehen Trigger standardmäßig. BULK INSERT und bcp lösen sie nur mit FIRE_TRIGGERS aus. Ohne diese Option landen importierte Zeilen ohne Protokolleintrag in der Tabelle.
Ändert sich der Schlüssel selbst, kippt die Einordnung. Der FULL OUTER JOIN verbindet inserted und deleted über kunde_id. Wird genau diese Spalte geändert, finden die beiden Seiten einander nicht — der Trigger schreibt ein DELETE für den alten und ein INSERT für den neuen Wert statt eines UPDATE. Bei einem echten Primärschlüssel ist das selten, aber wo fachliche Schlüssel geändert werden können, gehört der Join auf eine stabile Spalte oder die Klassifikation muss anders erfolgen.
Bei Verbindungs-Pooling ist der Benutzer nutzlos. Meldet sich die Anwendung mit einem technischen Dienstkonto an, steht in jedem Protokolleintrag derselbe Name. Der echte Endbenutzer muss dann von der Anwendung mitgegeben werden — über SESSION_CONTEXT (ab SQL Server 2016) oder das ältere CONTEXT_INFO:
-- In der Anwendung, direkt nach dem Verbindungsaufbau:
EXEC sys.sp_set_session_context @key = N'benutzer', @value = N'app-benutzer-4711';
-- Im Trigger (so steht es oben schon):
, COALESCE(CONVERT(SYSNAME, SESSION_CONTEXT(N'benutzer')), ORIGINAL_LOGIN())
Der COALESCE ist der Grund, warum der Verursacher im Trigger und nicht als Vorgabewert gesetzt wird: Gibt die Anwendung einen Benutzer mit, gewinnt der; direkte Zugriffe über das Management Studio landen weiterhin mit ihrem Anmeldenamen im Protokoll.
Die Schreiblast verdoppelt sich. Jede Änderung erzeugt einen zweiten Schreibvorgang, im Transaktionsprotokoll ebenso. Bei Tabellen mit hoher Änderungsrate ist das spürbar — und der Punkt, an dem sich die Frage nach einer Alternative wirklich stellt. Was ein Datenbankserver an Ein- und Ausgabe verkraftet und wo die Grenzen liegen, behandelt unser Artikel zu Windows unter dem Datenbankserver.
Was das Protokoll rechtlich mit sich bringt
Ein Änderungsprotokoll ist selten eine rein technische Angelegenheit. Es hält fest, welcher Mensch wann welchen Wert verändert hat — und speichert dabei in aller Regel auch Daten Dritter, im Beispiel oben das Kreditlimit eines Kunden. Damit ist die Protokolltabelle datenschutzrechtlich eine eigenständige Verarbeitung: mit eigenem Zweck, eigener Rechtsgrundlage, eigener Frist und einem eigenen, engeren Kreis von Zugriffsberechtigten. Sie erbt diese Dinge nicht von der Fachtabelle, aus der sie gespeist wird.
Mindestens die folgenden Punkte gehören geklärt, bevor der Trigger produktiv geht — nicht danach. Vollständig ist die Liste nicht; sie benennt das, was in technischen Anleitungen am häufigsten fehlt.
Zuerst: Warum darf überhaupt protokolliert werden? Das ist die Frage, die vor allen anderen kommt, und sie wird am häufigsten übersprungen. Auch eine gut gemeinte Protokollierung braucht eine Rechtsgrundlage nach Art. 6 Abs. 1 DSGVO — bei Beschäftigtendaten regelmäßig das berechtigte Interesse nach Buchstabe f, mit einer Abwägung, die dokumentiert wird und nicht nur gedacht ist. Dazu gehören zwei weitere Pflichten, die keinen Aufschub kennen: Beschäftigte und betroffene Kunden sind über die Protokollierung zu informieren (Art. 13, 14 DSGVO) — eine heimlich eingeführte Protokolltabelle ist der Klassiker unter den Fehlern in genau diesem Szenario —, und die Verarbeitung gehört in das Verzeichnis von Verarbeitungstätigkeiten (Art. 30). Wird systematisch und umfangreich Verhalten von Beschäftigten erfasst, ist zusätzlich zu prüfen, ob eine Datenschutz-Folgenabschätzung nötig wird (Art. 35 Abs. 3 lit. b).
Aufbewahrung ist zu begründen, nicht zu maximieren. „Wir behalten das für alle Fälle" ist kein Zweck. Wie lange ein Protokoll vorgehalten wird, ergibt sich aus dem Grund, aus dem es geführt wird: eine handelsrechtliche Aufbewahrungsfrist, eine vertragliche Nachweispflicht, ein internes Kontrollverfahren. Aus diesem Grund folgt eine Frist, und aus der Frist ein Löschlauf. Ein Protokoll ohne Löschkonzept wächst nicht nur technisch unbegrenzt, es wird mit der Zeit auch rechtlich schwerer zu verteidigen.
Der Verzicht auf Fremdschlüssel hat eine Kehrseite. Weiter oben steht der Rat, die Protokolltabelle ohne Fremdschlüssel zu bauen — technisch richtig, weil das Protokoll den gelöschten Datensatz überleben soll. Genau das heißt aber: Wird ein Kunde aus der Fachtabelle entfernt, bleiben seine alten Werte im Protokoll stehen. Wenn dieser Löschvorgang eine Betroffenenanfrage erfüllen soll, greift er zu kurz. Der Löschlauf muss die Protokolltabelle ausdrücklich mit erfassen, und wo Aufbewahrungspflicht und Löschanspruch kollidieren, ist die übliche Antwort nicht „alles behalten", sondern eine eingeschränkte Verarbeitung nach Art. 18 Abs. 1 lit. b bzw. Art. 17 Abs. 3 lit. b DSGVO: gesperrt, nicht mehr im Alltagszugriff, aber für den Nachweiszweck vorhanden.
Wo ein Betriebsrat besteht, redet er mit. Eine Tabelle, die festhält, welcher Mitarbeiter wann welchen Datensatz angefasst hat, ist eine technische Einrichtung, die zur Überwachung von Verhalten und Leistung geeignet ist. Für die Mitbestimmung nach § 87 Abs. 1 Nr. 6 BetrVG genügt diese Eignung — auf die Absicht kommt es ausdrücklich nicht an, und der Einwand „wir werten das doch gar nicht aus" trägt nicht. In Behörden gilt über die Personalvertretungsgesetze das Gleiche.
Die Einschränkung im ersten Halbsatz ist wichtig: § 87 BetrVG setzt einen bestehenden Betriebsrat voraus, und dessen Errichtung ist freiwillig. In Betrieben ohne Betriebsrat — bei Selbstständigen und kleinen Unternehmen der Normalfall — gibt es kein Mitbestimmungsrecht. Die datenschutzrechtlichen Pflichten oben gelten davon völlig unberührt weiter; sie hängen an keiner Arbeitnehmervertretung.
Wo es einen Betriebsrat gibt, ist er zu beteiligen, üblicherweise über eine Betriebsvereinbarung, die Zweck, Aufbewahrungsdauer, Auswertungsgrenzen und den Kreis der Zugriffsberechtigten festlegt. „Beteiligung" trifft es dabei genauer als „Zustimmung": Kommt keine Einigung zustande, entscheidet die Einigungsstelle, deren Spruch die Einigung ersetzt (§ 87 Abs. 2 BetrVG) — ein absolutes Vetorecht hat der Betriebsrat also nicht. Wird er übergangen, drohen ein Unterlassungsanspruch und im Ergebnis die Untersagung des Systembetriebs, dazu das Bußgeldrisiko aus dem Datenschutzrecht und ein Vertrauensschaden, der schwerer wiegt als beides. Dass die Erkenntnisse aus einem solchen Protokoll vor Gericht automatisch unverwertbar wären, gehört dagegen ins Reich der Legende: Bei offener Protokollierung nimmt das Bundesarbeitsgericht ein Verwertungsverbot regelmäßig nicht an, selbst wenn die Einführung fehlerhaft war (BAG, Urteil vom 29.06.2023 – 2 AZR 296/22). Angreifbar bleibt die Einführung trotzdem.
Dazu kommt das Naheliegende: Wer das Protokoll lesen darf, ist eine eigene Entscheidung und nicht dieselbe wie „wer die Fachtabelle lesen darf". Ein SELECT-Recht für alle auf eine Tabelle, in der Personalnamen neben Kundenwerten stehen, macht aus einem Kontrollinstrument eine Auskunftei.
Das ersetzt keine Rechtsberatung — die Ausgestaltung hängt an Branche, Zweck und Betriebsgröße. Es ersetzt aber die Annahme, ein Audit-Trigger sei allein eine Frage von T-SQL.
Wann etwas anderes die bessere Wahl ist
SQL Server bringt drei Verfahren mit, die je nach Frage besser passen als ein selbstgebauter Trigger.
Change Tracking merkt sich nur, dass eine Zeile geändert wurde — ohne Werte und ohne Verursacher. Für Synchronisierung zwischen Systemen ist das genau richtig und sehr günstig; als Protokoll taugt es nicht.
Change Data Capture liest die Änderungen asynchron aus dem Transaktionsprotokoll und legt alte wie neue Werte ab, ohne die schreibende Transaktion zu belasten. Seit SQL Server 2016 SP1 ist es auch in der Standard Edition verfügbar. Der Preis: Es braucht laufende SQL-Server-Agent-Aufträge, und den Endbenutzer kennt es genauso wenig wie Change Tracking.
Temporal Tables führen automatisch eine Verlaufstabelle und beantworten die Frage „wie sah dieser Datensatz am 3. Mai aus" mit einer Abfrage (FOR SYSTEM_TIME AS OF). Für Historisierung ist das der eleganteste Weg — aber auch hier steht kein Verursacher in den Daten.
Die Entscheidung in einem Satz: Brauchst du das Wer, führt an einem Trigger (oder an einer Anwendung, die es mitliefert) kein Weg vorbei. Geht es nur um den Zustandsverlauf, nimm Temporal Tables. Geht es um Datenverteilung, nimm Change Tracking oder CDC.
Hinweis: Editions- und Versionsangaben Stand August 2026. Der Funktionsumfang der SQL-Server-Editionen ändert sich zwischen Hauptversionen — vor einer Entscheidung in der Dokumentation zur eingesetzten Version prüfen.
Häufige Fragen (FAQ)
Wie protokolliere ich in SQL Server, wer eine Zeile geändert hat?
Mit einem AFTER-Trigger auf der Tabelle, der aus den virtuellen Tabellen inserted und deleted liest und das Ergebnis in eine Protokolltabelle schreibt. Den Anmeldenamen liefert ORIGINAL_LOGIN(). Läuft die Anwendung über ein gemeinsames Dienstkonto, muss sie den echten Benutzer per SESSION_CONTEXT mitgeben — sonst steht in jedem Eintrag derselbe Name.
Warum protokolliert mein Trigger nur eine von vielen geänderten Zeilen?
Weil der Trigger einmal pro Anweisung läuft, nicht pro Zeile. Ein UPDATE über 4.000 Zeilen ruft ihn genau einmal auf, und inserted enthält dann alle 4.000. Wer im Trigger mit SELECT @variable = spalte FROM inserted arbeitet, bekommt einen beliebigen Wert daraus und verliert den Rest. Die Lösung ist immer ein mengenbasiertes INSERT … SELECT.
Verlangsamt ein Audit-Trigger die Datenbank?
Ja, messbar: Jede Änderung erzeugt einen zweiten Schreibvorgang, der auch im Transaktionsprotokoll landet. Bei Tabellen mit wenigen Änderungen pro Minute fällt das nicht auf, bei Massenverarbeitung schon. Dort ist Change Data Capture die bessere Wahl, weil es die schreibende Transaktion nicht belastet.
Was passiert mit dem Protokoll bei einem Rollback?
Es verschwindet mit. Der Trigger läuft in derselben Transaktion wie die Änderung — wird die zurückgerollt, gilt das auch für den Protokolleintrag. Das ist gewollt, bedeutet aber, dass sich abgebrochene Änderungsversuche mit einem Trigger nicht festhalten lassen.
Löst TRUNCATE TABLE einen Trigger aus?
Nein. TRUNCATE arbeitet auf Metadatenebene und protokolliert keine einzelnen Zeilen, deshalb feuert kein DML-Trigger. Wenn die Vollständigkeit des Protokolls zählt, muss das ALTER TABLE-Recht entsprechend eingeschränkt werden. Dasselbe gilt für BULK INSERT und bcp, die Trigger nur mit der Option FIRE_TRIGGERS auslösen.
Trigger oder Temporal Tables — was ist besser?
Das hängt an der Frage, die beantwortet werden soll. Temporal Tables zeigen, wie ein Datensatz zu einem beliebigen Zeitpunkt aussah, und sind dafür bequemer und robuster als jeder selbstgebaute Trigger. Sie sagen aber nicht, wer die Änderung veranlasst hat. Wird das gebraucht — bei Nachweispflichten der Regelfall —, führt am Trigger kein Weg vorbei, oder beides wird kombiniert.
Wie lange darf ich die Protokolltabelle aufbewahren?
So lange, wie der Zweck es trägt, aus dem das Protokoll geführt wird — eine handelsrechtliche Frist, eine vertragliche Nachweispflicht, ein Kontrollverfahren. „Unbegrenzt, für alle Fälle" ist kein Zweck und lässt sich im Zweifel nicht verteidigen. Aus dem Zweck folgt eine Frist, aus der Frist ein Löschlauf, und der muss die Protokolltabelle ausdrücklich einschließen: Weil sie bewusst ohne Fremdschlüssel gebaut ist, überlebt sie das Löschen des Datensatzes, auf den sie sich bezieht. Welche Frist im konkreten Fall gilt, gehört zur oder zum Datenschutzbeauftragten, nicht in einen Fachartikel.
Ist ein Audit-Trigger mitbestimmungspflichtig?
Sofern im Unternehmen ein Betriebsrat besteht: in aller Regel ja, sobald der Trigger festhält, welcher Mitarbeiter etwas geändert hat. Eine solche Tabelle ist eine technische Einrichtung, die zur Überwachung von Verhalten und Leistung geeignet ist, und für die Mitbestimmung nach § 87 Abs. 1 Nr. 6 BetrVG genügt diese Eignung — die Absicht ist unerheblich. Üblich ist eine Betriebsvereinbarung über Zweck, Aufbewahrungsdauer, Auswertungsgrenzen und Zugriffsberechtigte; kommt keine Einigung zustande, entscheidet die Einigungsstelle (§ 87 Abs. 2 BetrVG), ein Vetorecht hat der Betriebsrat also nicht. Gibt es keinen Betriebsrat, entfällt die Mitbestimmung — die Datenschutzpflichten bleiben davon unberührt. Die Ausgestaltung im Einzelfall gehört zur oder zum Datenschutzbeauftragten, nicht in einen Fachartikel.
Wie verhindere ich, dass ein Fehler im Trigger das UPDATE scheitern lässt?
Gar nicht vollständig — genau das ist das Wesen eines Triggers in derselben Transaktion. Man kann das Risiko aber klein halten: Die Protokolltabelle bekommt keine Fremdschlüssel, keine Prüfbedingungen, keinen eigenen Trigger und großzügig bemessene Spalten. Je einfacher sie ist, desto weniger Gründe hat sie zu scheitern.
Quellen
Die Versions- und Verhaltensangaben stammen aus der Herstellerdokumentation, nicht aus zweiter Hand. Wer eine einzelne Aussage nachschlagen will, findet sie hier:
- DML-Trigger verwenden — Ausführung einmal je Anweisung, nicht je Zeile; Trigger und Transaktionsklammer
- Die Tabellen inserted und deleted — Belegung bei INSERT, UPDATE und DELETE
- CREATE TRIGGER —
CREATE OR ALTERab SQL Server 2016 SP1, kein Auslösen durch TRUNCATE TABLE - SESSION_CONTEXT — ab SQL Server 2016, Ablösung von
CONTEXT_INFO - Temporal Tables — ab SQL Server 2016, Abfrage über
FOR SYSTEM_TIME - Change Data Capture — Editionsverfügbarkeit, Bindung an den SQL Server Agent
- Change Tracking — Abgrenzung zu CDC, kein Werteverlauf
Die rechtlichen Einordnungen im Abschnitt zur Aufbewahrung sind eine Orientierung, keine Rechtsberatung — sie ersetzen die Abstimmung mit der oder dem Datenschutzbeauftragten und der Arbeitnehmervertretung nicht.
Jetzt loslegen
Trigger sind nur ein Teil dessen, was T-SQL für datenbanknahe Logik bereithält — Fehlerbehandlung, Transaktionssteuerung und mengenbasiertes Denken gehören dazu, und genau daran entscheidet sich, ob ein Protokoll vollständig ist. Das Seminar SQL Server T-SQL Programmierung behandelt beides ausführlich, inklusive der Sperr- und Transaktionsfragen, die bei Triggern schnell relevant werden. Wer beim Abfragen selbst noch Boden gutmachen will, findet ihn in SQL Fortgeschritten; und wenn die Schreiblast durch das Protokoll zum Thema wird, ist Datenbankübergreifendes Performance-Tuning der passende Kurs — dort geht es systemneutral um Ausführungspläne, Indexstrategie und Sperrverhalten.
Wie andere Datenbanksysteme dieselbe Aufgabe lösen — PostgreSQL etwa mit Zeilentriggern und Übergangstabellen —, steht in unserem Systemvergleich.
Die verlinkten Seminare gibt es als offenes Seminar mit festen Terminen, im virtuellen Klassenraum und als Inhouse-Schulung bei euch vor Ort. Welches Format passt und welche Termine anstehen, klären wir in der Anfrage. Das Angebot richtet sich an Unternehmen, Behörden und Selbstständige.