SQL Server-Praxis

SQL-Server-Temporal-Historie: Was AS OF wirklich bedeutet

Lesen Sie frühere Zeilenversionen und unterscheiden Sie Systemzeit, fachliche Gültigkeit, Transaktionsgrenzen und zusätzliche Anforderungen an Audits.

Ändert sich ein Preis von 10 auf 12, bleibt in einer normalen Tabelle nur der neue Wert, sofern die Anwendung keine Historie schreibt. Eine systemversionierte temporale Tabelle kann frühere Versionen automatisch erhalten. Das unterstützt Untersuchungen, beantwortet aber nicht jede historische Frage gleich.

Unterscheiden Sie den nach SQL-Server-Systemzeit gespeicherten Wert, die fachlich gewünschte Gültigkeit und die verantwortliche Person. Temporal History beantwortet unmittelbar die erste Frage. Die anderen brauchen zusätzliche Daten und einen definierten Ablauf.

Aktuelle und frühere Versionen beobachten

Das Beispiel ab SQL Server 2016 erstellt permanente Übungstabellen. Verwenden Sie Autocommit ohne umschließende Transaktion.

-- Use a disposable database, autocommit, and no enclosing transaction.
IF @@TRANCOUNT <> 0 THROW 50001, 'Use a separate practice connection.', 1;
CREATE TABLE dbo.PriceTemporalDemo (
    ProductId int NOT NULL PRIMARY KEY,
    Price decimal(12,2) NOT NULL,
    ValidFrom datetime2(7) GENERATED ALWAYS AS ROW START NOT NULL,
    ValidTo datetime2(7) GENERATED ALWAYS AS ROW END NOT NULL,
    PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
) WITH (SYSTEM_VERSIONING = ON (
    HISTORY_TABLE = dbo.PriceTemporalDemoHistory
));
INSERT dbo.PriceTemporalDemo(ProductId, Price) VALUES (1, 10.00);
DECLARE @BeforeChange datetime2(7) = SYSUTCDATETIME();
WAITFOR DELAY '00:00:01';
UPDATE dbo.PriceTemporalDemo SET Price = 12.00 WHERE ProductId = 1;
SELECT ProductId, Price FROM dbo.PriceTemporalDemo WHERE ProductId = 1;
SELECT ProductId, Price, ValidFrom, ValidTo
FROM dbo.PriceTemporalDemo FOR SYSTEM_TIME AS OF @BeforeChange
WHERE ProductId = 1;

Die aktuelle Abfrage liefert 12,00, AS OF @BeforeChange liefert 10,00. Die temporale Syntax durchsucht passende aktuelle und historische Versionen. Eine manuelle Vereinigung beider Tabellen ist für diese Zeitpunktabfrage nicht erforderlich.

Die Periodenspalten enthalten UTC-datetime2-Werte. AS OF wählt eine Version mit Beginn vor oder am gewünschten Zeitpunkt und Ende danach. Die obere Grenze ist ausgeschlossen. Übergeben Sie einen korrekt nach UTC umgerechneten Parameter statt einer lokalen Uhrzeit mit vermutetem Versatz.

Die Pause trennt lediglich die Demonstrationszeitpunkte. Sie gehört nicht in die Produktionslogik. Ohne klare Trennung können sehr kurze Versuche schwer lesbare Zeitgrenzen erzeugen, besonders bei veränderter Datentypgenauigkeit.

Alle sichtbaren Versionen zeigen die Intervalle.

SELECT ProductId, Price, ValidFrom, ValidTo
FROM dbo.PriceTemporalDemo FOR SYSTEM_TIME ALL
WHERE ProductId = 1
ORDER BY ValidFrom, ValidTo;

Auch eine Aktualisierung auf denselben Wert kann Historie erzeugen. Vermeiden Sie unnötige Schreibarbeit, wenn daraus teures Wachstum entsteht. Fachlich bedeutende Änderungen dürfen aber nicht allein zur Platzersparnis entfallen.

Die Transaktionszeit richtig verstehen

Periodengrenzen beruhen auf dem Beginn der Transaktion, nicht auf COMMIT. Eine lange Transaktion kann eine Version erzeugen, deren Systembeginn vor dem Zeitpunkt liegt, zu dem andere Verbindungen ihren bestätigten Wert sehen konnten. AS OF folgt dieser Semantik und zeichnet nicht exakt die Sicht jedes damaligen Lesers auf.

Mehrere Änderungen derselben Zeile innerhalb einer Transaktion können Versionen mit Dauer null erzeugen. Temporale Abfrageklauseln blenden solche Historienversionen aus. Direktes Lesen der Historientabelle kann daher zusätzliche Zeilen zeigen. Nicht jeder fehlende Zwischenstand bedeutet Datenverlust.

Soll ein heute eingetragener Preis erst nächsten Monat gelten, benötigt er ein separates fachliches Gültigkeitsdatum. Die generierte Systemperiode sollte nicht für diese Planung umgedeutet werden. Auch eine nachträgliche Korrektur braucht die Trennung zwischen fachlichem Zeitpunkt und dem Zeitpunkt der Erfassung.

AS OF für mehrere temporale Tabellen kann historische Joins vereinfachen. Prüfen Sie trotzdem, welche weiteren Tabellen beteiligt sind. Eine alte Bestellung mit dem heutigen veränderlichen Kategorienamen ergibt einen zeitlich gemischten Bericht, obwohl seine Grunddaten historisch sind.

Historie als echten Datenbestand betreiben

Schätzen Sie Wachstum anhand von Änderungsrate und Zeilenbreite statt nur aktuellen Zeilen. Eine kleine häufig aktualisierte Tabelle kann viel Historie erzeugen. Indizieren Sie den tatsächlichen Untersuchungsfall: viele Versionen eines Produkts unterscheiden sich von einer vollständigen Zeitpunktrekonstruktion.

Aufbewahrung und Bereinigung brauchen klare Regeln. Entfernte Versionen können nicht mehr durch einen Bericht rekonstruiert werden. Dokumentieren Sie den verfügbaren Horizont und überwachen Sie die zur Version passende Bereinigung.

Temporal History ersetzt keine Sicherung und kein unveränderliches Audit. Verantwortliche Person und fachlicher Grund werden nicht automatisch erfasst. Privilegierte Wartung kann die Konfiguration verändern. Ergänzen Sie benötigte Zuordnung separat und schützen Sie ihren Zugriff.

Schemaänderungen und Wartung betreffen aktuelle und historische Tabelle gemeinsam. SYSTEM_VERSIONING OFF unterbricht die automatische Erfassung. Beim erneuten Aktivieren muss die beabsichtigte Historientabelle ausdrücklich zugeordnet werden, damit nicht versehentlich eine neue entsteht.

Prüfen Sie Aktualisierung, Löschung, lange Transaktionen, mehrere Änderungen innerhalb einer Transaktion und exakte Übergangsgrenzen. Der Entwurf soll gespeicherte Systemgeschichte und fachliche Bedeutung nachvollziehbar auseinanderhalten.

Technische Referenzen: Microsoft Learn: Query temporal data · Microsoft Learn: Temporal considerations.

Frage zu diesem Artikel

Haben Sie eine Frage zu diesem Thema?

Beschreiben Sie, was Sie bewerten oder wo Sie nicht weiterkommen. Wir antworten mit einer praktischen Empfehlung.

Inquiries are not enabled in this preview.

Eine Frage zu diesem Artikel stellen