Erstellen einer temporären Tabelle mit Systemversionsverwaltung
Gilt für: SQL Server 2016 (13.x) und höher Azure SQL-Datenbank Azure SQL Managed Instance
Es gibt drei Methoden zum Erstellen einer temporalen Tabelle mit Systemversionsverwaltung, die sich darin unterscheiden, wie die Verlaufstabelle angegeben wird:
Temporale Tabelle mit einer anonymen Verlaufstabelle: Sie geben das Schema der aktuellen Tabelle an und lassen eine entsprechende Verlaufstabelle mit einem automatisch generierten Namen vom System erstellen.
Temporale Tabelle mit einer Standardverlaufstabelle: Sie geben den Namen des Verlaufstabellenschemas und der Tabelle an und lassen vom System eine Verlaufstabelle in diesem Schema erstellen.
Temporale Tabelle mit einer vorab erstellten, benutzerdefinierten Verlaufstabelle: Sie erstellen eine Verlaufstabelle, die Ihren Anforderungen am besten entspricht, und verweisen dann beim Erstellen der temporalen Tabelle auf diese Tabelle.
Erstellen einer temporalen Tabelle mit anonymer Verlaufstabelle
Das Erstellen einer temporalen Tabelle mit einer anonymen Verlaufstabelle ist eine praktische Möglichkeit für das schnelle Erstellen von Objekten insbesondere in Prototyp- und Testumgebungen. Es ist auch die einfachste Möglichkeit, eine temporale Tabelle zu erstellen, da keine Parameter in der SYSTEM_VERSIONING
-Klausel erforderlich sind. Im folgenden Beispiel wird eine neue Tabelle mit aktivierter Systemversionsverwaltung erstellt, ohne den Namen der Verlaufstabelle zu definieren.
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON);
Hinweise
Für eine temporale Tabelle mit Systemversionsverwaltung muss ein Primärschlüssel und genau eine PERIOD FOR SYSTEM_TIME
mit zwei datetime2-Spalten definiert sein, die als GENERATED ALWAYS AS ROW START
oder GENERATED ALWAYS AS ROW END
deklariert sind.
Die PERIOD
-Spalten dürfen keine NULL-Werte zulassen, auch wenn keine Angabe zur NULL-Zulässigkeit gemacht wurde. Wenn für die PERIOD
-Spalten explizit angegeben ist, dass NULL-Werte zulässig sind, tritt bei der Anweisung CREATE TABLE
ein Fehler auf.
Das Schema der Verlaufstabelle muss im Hinblick auf Spaltenanzahl, Spaltennamen, Sortierung und Datentypen stets an die aktuelle oder temporale Tabelle angepasst sein.
Eine anonyme Verlaufstabelle wird automatisch im gleichen Schema wie die aktuelle oder temporale Tabelle erstellt.
Der Name der anonymen Verlaufstabelle weist das folgende Format auf: MSSQL_TemporalHistoryFor_<current_temporal_table_object_id>_<suffix>
. Das Suffix ist optional und wird nur hinzugefügt, wenn der erste Teil des Tabellennamens nicht eindeutig ist.
Die Verlaufstabelle wird als Rowstoretabelle erstellt. Sofern möglich, wird die PAGE
-Komprimierung angewendet; andernfalls wird die Verlaufstabelle nicht komprimiert. Einige Tabellenkonfigurationen, z. B. SPARSE
-Spalten, lassen beispielsweise keine Komprimierung zu.
Für die Verlaufstabelle wird ein gruppierter Standardindex mit einem automatisch generierten Namen im Format IX_<history_table_name>
erstellt. Der gruppierte Index enthält die PERIOD
-Spalten (Ende, Anfang).
Informationen zum Erstellen der aktuellen Tabelle als speicheroptimierte Tabelle finden Sie unter Temporale Tabellen mit Systemversionsverwaltung für speicheroptimierte Tabellen.
Erstellen einer temporären Tabelle mit Standardverlaufstabelle
Das Erstellen einer temporalen Tabelle mit einer standardmäßigen Verlaufstabelle ist eine praktische Möglichkeit, wenn Sie die Benennung steuern möchten, die Verlaufstabelle aber trotzdem mit der Standardkonfiguration vom System erstellt werden soll. Im folgenden Beispiel wird eine neue Tabelle mit aktivierter Systemversionsverwaltung erstellt, wobei der Name der Verlaufstabelle explizit definiert wird.
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.DepartmentHistory));
Hinweise
Die Verlaufstabelle wird unter Anwendung der gleichen Regeln erstellt, die für das Erstellen einer „anonymen“ Verlaufstabelle gelten. Allerdings gelten die folgenden Regeln speziell für die benannte Verlaufstabelle.
Der Schemaname ist für den Parameter
HISTORY_TABLE
obligatorisch.Wenn das angegebene Schema nicht vorhanden ist, tritt bei der Anweisung
CREATE TABLE
ein Fehler auf.Wenn die im Parameter
HISTORY_TABLE
angegebene Tabelle bereits vorhanden ist, wird sie mit der neu erstellten temporalen Tabelle auf Schemakonsistenz und temporale Datenkonsistenz verglichen. Wenn Sie eine ungültige Verlaufstabelle angeben, tritt bei der AnweisungCREATE TABLE
ein Fehler auf.
Erstellen einer temporären Tabelle mit benutzerdefinierter Verlaufstabelle
Das Erstellen einer temporalen Tabelle mit einer benutzerdefinierten Verlaufstabelle ist eine praktische Möglichkeit, wenn Benutzer*innen eine Verlaufstabelle mit bestimmten Speicheroptionen und zusätzlichen Indizes festlegen möchten. Im folgenden Beispiel wird eine benutzerdefinierte Verlaufstabelle mit einem Schema erstellt, das auf die zu erstellende temporale Tabelle abgestimmt ist. Für diese benutzerdefinierte Verlaufstabelle werden ein gruppierter Columnstore-Index und ein weiterer nicht gruppierter Rowstore-Index (B-Struktur) für Punktsuchen erstellt. Nach Erstellung der benutzerdefinierten Verlaufstabelle wird die temporale Tabelle unter Angabe der benutzerdefinierten Verlaufstabelle als Standardverlaufstabelle erstellt.
Hinweis
In der Dokumentation wird der Begriff „B-Struktur“ im Allgemeinen in Bezug auf Indizes verwendet. In Zeilenspeicherindizes implementiert die Datenbank-Engine eine B+-Struktur. Das gilt nicht für Columnstore-Indizes oder Indizes in speicheroptimierten Tabellen. Weitere Informationen finden Sie im Leitfaden zur Architektur und zum Entwerfen von SQL Server- und Azure SQL-Indizes.
CREATE TABLE DepartmentHistory
(
DeptID INT NOT NULL,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 NOT NULL,
ValidTo DATETIME2 NOT NULL
);
GO
CREATE CLUSTERED COLUMNSTORE INDEX IX_DepartmentHistory ON DepartmentHistory;
CREATE NONCLUSTERED INDEX IX_DepartmentHistory_ID_Period_Columns
ON DepartmentHistory (ValidTo, ValidFrom, DeptID);
GO
CREATE TABLE Department
(
DeptID int NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.DepartmentHistory));
Hinweise
Wenn Sie analytische Abfragen für die historischen Daten ausführen möchten, die Aggregate oder Fensterfunktionen einsetzen, ist es zum Zwecke der Leistung bei Komprimierung und Abfrage sehr zu empfehlen, einen gruppierten Columnstore als primären Index zu erstellen.
Wenn Sie temporale Tabellen für die Datenüberwachung verwenden möchten (d. h. wenn Sie Verlaufsänderungen für eine bestimmte Zeile in der aktuellen Tabelle suchen möchten), sollten Sie eine Rowstore-Verlaufstabelle mit einem gruppierten Index erstellen.
Die Verlaufstabelle kann keine Primärschlüssel, Fremdschlüssel, eindeutige Indizes, Tabelleneinschränkungen oder Trigger enthalten. Sie kann nicht zur Erfassung von Änderungsdaten, zur Änderungsnachverfolgung oder zur Transaktionsreplikation oder Mergereplikation konfiguriert werden.
Ändern einer nicht temporalen Tabelle in eine temporale Tabelle mit Systemversionsverwaltung
Sie können die Systemversionsverwaltung für eine vorhandene Tabelle aktivieren, z. B., wenn Sie eine benutzerdefinierte temporale Lösung zu integrierter Unterstützung migrieren möchten.
Angenommen, Sie verfügen über eine Gruppe von Tabellen, bei denen die Versionsverwaltung mit Triggern implementiert ist. Die Verwendung temporärer Systemversionsverwaltung ist weniger komplex und bietet zusätzliche Vorteile, z. B.:
- Unveränderlichen Verlauf
- Neue Syntax für „Zeitreiseabfragen“
- Eine bessere DML-Leistung
- Minimale Wartungskosten
Ziehen Sie beim Konvertieren einer vorhandenen Tabelle die Verwendung der Klausel HIDDEN
in Betracht, um die neuen PERIOD
-Spalten (die datetime2-Spalten ValidFrom
und ValidTo
) auszublenden und so Auswirkungen auf vorhandene Anwendungen zu vermeiden, die Spaltennamen nicht explizit angeben (z.B. SELECT *
oder INSERT
ohne Spaltenliste) und keine neuen Spalten verarbeiten können.
Hinzufügen der Versionsverwaltung zu nicht temporären Tabellen
Wenn Sie das Nachverfolgen von Änderungen für eine nicht temporale Tabelle mit den Daten starten möchten, müssen Sie die PERIOD
-Definition hinzufügen und optional einen Namen für die leere Verlaufstabelle angeben, die SQL Server für Sie erstellt:
CREATE SCHEMA History;
GO
ALTER TABLE InsurancePolicy ADD
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN
CONSTRAINT DF_InsurancePolicy_ValidFrom DEFAULT SYSUTCDATETIME(),
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN
CONSTRAINT DF_InsurancePolicy_ValidTo DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999'),
PERIOD FOR SYSTEM_TIME(ValidFrom, ValidTo);
GO
ALTER TABLE InsurancePolicy
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = History.InsurancePolicy));
GO
Wichtig
Die Genauigkeit für DATETIME2
muss mit der Genauigkeit für die zugrunde liegende Tabelle übereinstimmen.
Hinweise
Das Hinzufügen von Spalten, die keine NULL-Werte zulassen, mit Standardwerten zu einer vorhandenen Tabelle mit Daten ist in allen Editionen außer SQL Server Enterprise Edition ein Datengrößenvorgang (in SQL Server Enterprise Edition wäre es ein Metadatenvorgang). Bei einer vorhandenen großen Verlaufstabelle mit Daten in SQL Server Standard Edition kann das Hinzufügen einer Nicht-NULL-Spalte ein aufwendiger Vorgang sein.
Einschränkungen für Spalten des Zeitraumstarts und -endes müssen sorgfältig gewählt werden:
Der Standardwert für die Startspalte gibt an, ab welchem Zeitpunkt vorhandene Zeilen als gültig betrachtet werden. Es kann kein Zeitpunkt in der Zukunft als datetime-Wert angegeben werden.
Die Endzeit muss als maximaler Wert für eine bestimmte datetime2-Genauigkeit angegeben werden, z. B.
9999-12-31 23:59:59
oder9999-12-31 23:59:59.9999999
.
Durch das Hinzufügen von PERIOD
wird für die aktuelle Tabelle eine Datenkonsistenzprüfung durchgeführt, um sicherzustellen, dass die vorhandenen Werte für Zeitraumspalten gültig sind.
Wenn bei der Aktivierung von SYSTEM_VERSIONING
eine vorhandene Verlaufstabelle angegeben wird, erfolgt eine Datenkonsistenzprüfung der aktuellen Tabelle und der Verlaufstabelle. Diese Prüfung kann übersprungen werden, indem Sie DATA_CONSISTENCY_CHECK = OFF
als zusätzlichen Parameter angeben.
Migrieren von vorhandenen Tabellen zu integrierter Unterstützung
Dieses Beispiel zeigt, wie eine vorhandene Lösung basierend auf Triggern zu integrierter temporärer Unterstützung migriert wird. In diesem Beispiel wird angenommen, dass in der aktuellen benutzerdefinierten Lösung die aktuellen und die historischen Daten auf zwei getrennte Benutzertabellen aufgeteilt sind (ProjectTaskCurrent
und ProjectTaskHistory
).
Wenn Ihre vorhandene Lösung sowohl die aktuellen als auch die historischen Zeilen in einer einzigen Tabelle speichert, sollten Sie die Daten auf zwei Tabellen aufteilen, bevor Sie die in folgendem Beispiel gezeigten Migrationsschritte ausführen. Legen Sie zuerst den Trigger auf der zukünftigen temporären Tabelle ab. Stellen Sie dann sicher, dass die PERIOD
-Spalten keine NULL-Werte zulassen.
/* Drop trigger on future temporal table */
DROP TRIGGER ProjectCurrent_OnUpdateDelete;
/* Make sure that future period columns are non-nullable */
ALTER TABLE ProjectTaskCurrent
ALTER COLUMN [ValidFrom] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskCurrent
ALTER COLUMN [ValidTo] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory
ALTER COLUMN [ValidFrom] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory
ALTER COLUMN [ValidTo] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskCurrent ADD PERIOD
FOR SYSTEM_TIME([ValidFrom], [ValidTo]);
ALTER TABLE ProjectTaskCurrent SET (
SYSTEM_VERSIONING = ON (
HISTORY_TABLE = dbo.ProjectTaskHistory,
DATA_CONSISTENCY_CHECK = ON
)
);
Hinweise
Durch das Verweisen auf vorhandene Spalten in der PERIOD
-Definition wird für diese Spalten implizit generated_always_type
zu AS_ROW_START
und AS_ROW_END
geändert.
Durch das Hinzufügen von PERIOD
wird für die aktuelle Tabelle eine Datenkonsistenzprüfung durchgeführt, um sicherzustellen, dass die vorhandenen Werte für Zeitraumspalten gültig sind.
Wir empfehlen Ihnen dringend, SYSTEM_VERSIONING
mit DATA_CONSISTENCY_CHECK = ON
festzulegen, um Datenkonsistenzprüfungen für die vorhandenen Daten zu erzwingen.
Wenn ausgeblendete Spalten bevorzugt werden, verwenden Sie den Befehl ALTER TABLE [tableName] ALTER COLUMN [columnName] ADD HIDDEN;
.
Zugehöriger Inhalt
- Temporale Tabellen
- Erste Schritte mit temporalen Tabellen mit Systemversionsverwaltung
- Verwalten der Beibehaltung von Verlaufsdaten in temporalen Tabellen mit Systemversionsverwaltung
- Temporale Tabellen mit Systemversionsverwaltung für speicheroptimierte Tabellen
- CREATE TABLE (Transact-SQL)
- Ändern von Daten in einer temporalen Tabelle mit Systemversionsverwaltung
- Abfragen von Daten in einer temporalen Tabelle mit Systemversionsverwaltung
- Ändern des Schemas einer temporalen Tabelle mit Systemversionsverwaltung
- Beenden der Versionsverwaltung in einer temporalen Tabelle mit Systemversionsverwaltung