Een tijdelijke tabel met systeemversies maken
Van toepassing op: SQL Server 2016 (13.x) en latere versies
Azure SQL Database
Azure SQL Managed Instance
SQL-database in Microsoft Fabric
Er zijn drie manieren om een tijdelijke tabel met systeemversies te maken wanneer u overweegt hoe de geschiedenistabel wordt opgegeven:
Tijdelijke tabel met een anonieme geschiedenistabel: u geeft het schema van de huidige tabel op en laat het systeem een bijbehorende geschiedenistabel met automatisch gegenereerde naam maken.
Tijdelijke tabel met een standaardgeschiedenistabel: u geeft de schemanaam en tabelnaam van de geschiedenistabel op en laat het systeem een geschiedenistabel in dat schema maken.
Tijdtabel met een door de gebruiker gedefinieerde geschiedenis tabel die vooraf is gemaakt: u maakt een geschiedenistabel die het beste bij uw behoeften past en verwijst vervolgens naar die tabel tijdens het maken van een tijdtabel.
Een tijdelijke tabel maken met een anonieme geschiedenistabel
Het maken van een tijdelijke tabel met een anonieme geschiedenistabel is een handige optie voor het snel maken van objecten, met name in prototypes en testomgevingen. Het is ook de eenvoudigste manier om een tijdelijke tabel te maken, omdat hiervoor geen parameter in de SYSTEM_VERSIONING
-component is vereist. In het volgende voorbeeld wordt een nieuwe tabel gemaakt met systeemversiebeheer ingeschakeld zonder de naam van de geschiedenistabel te definiëren.
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);
Opmerkingen
Een tijdelijke tabel met systeemversie moet een gedefinieerde primaire sleutel hebben en precies één PERIOD FOR SYSTEM_TIME
gedefinieerd hebben met twee datetime2-kolommen, gedeclareerd als GENERATED ALWAYS AS ROW START
of GENERATED ALWAYS AS ROW END
.
De PERIOD
-kolommen worden altijd beschouwd als niet-nullable, zelfs als de nullbaarheid niet is gespecificeerd. Als de PERIOD
-kolommen expliciet als nul zijn gedefinieerd, mislukt de CREATE TABLE
-verklaring.
De geschiedenistabel moet altijd worden uitgelijnd met de huidige of tijdelijke tabel, met betrekking tot het aantal kolommen, kolomnamen, volgorde en gegevenstypen.
Er wordt automatisch een anonieme geschiedenistabel gemaakt in hetzelfde schema als de huidige of tijdelijke tabel.
De naam van de anonieme geschiedenistabel heeft de volgende indeling: MSSQL_TemporalHistoryFor_<current_temporal_table_object_id>_<suffix>
. Het achtervoegsel is optioneel en wordt alleen toegevoegd als het eerste deel van de tabelnaam niet uniek is.
De geschiedenistabel wordt gemaakt als een rowstore-tabel.
PAGE
compressie wordt toegepast indien mogelijk, anders wordt de geschiedenistabel niet gecomprimeerd. Sommige tabelconfiguraties, zoals SPARSE
kolommen, staan bijvoorbeeld geen compressie toe.
Er wordt een standaard geclusterde index gemaakt voor de geschiedenistabel met een automatisch gegenereerde naam in indeling IX_<history_table_name>
. De geclusterde index bevat de PERIOD
kolommen (einde, begin).
In de Fabric SQL-database wordt de gemaakte geschiedenistabel niet gespiegeld naar Fabric OneLake.
Als u de huidige tabel wilt creëren als een geheugen-geoptimaliseerde tabel, raadpleegt u systeem-geversioneerde temporele tabellen met geheugen-geoptimaliseerde tabellen.
Een tijdelijke tabel maken met een standaardgeschiedenistabel
Het maken van een tijdelijke tabel met een standaard geschiedenistabel is een handige optie wanneer u naamgeving wilt beheren en nog steeds afhankelijk bent van het systeem om de geschiedenistabel te maken met de standaardconfiguratie. In het volgende voorbeeld wordt een nieuwe tabel gemaakt met systeemversiebeheer ingeschakeld met de naam van de geschiedenistabel die expliciet is gedefinieerd.
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));
Opmerkingen
De geschiedenistabel wordt gemaakt met dezelfde regels als die van toepassing zijn op het maken van een 'anonieme' geschiedenistabel, met de volgende regels die specifiek van toepassing zijn op de benoemde geschiedenistabel.
De schemanaam is verplicht voor de parameter
HISTORY_TABLE
.Als het opgegeven schema niet bestaat, mislukt de
CREATE TABLE
instructie.Als de tabel die is opgegeven door de parameter
HISTORY_TABLE
al bestaat, wordt deze gevalideerd op basis van de zojuist gemaakte tijdelijke tabel in termen van schemaconsistentie en tijdelijke gegevensconsistentie. Als u een ongeldige geschiedenistabel opgeeft, mislukt de instructieCREATE TABLE
.
Een tijdelijke tabel maken met een door de gebruiker gedefinieerde geschiedenistabel
Het maken van een tijdelijke tabel met door de gebruiker gedefinieerde geschiedenistabel is een handige optie wanneer de gebruiker een geschiedenistabel met specifieke opslagopties en verschillende indexen wil opgeven die zijn afgestemd op historische query's. In het volgende voorbeeld wordt een door de gebruiker gedefinieerde geschiedenistabel gemaakt met een schema dat is afgestemd op de tijdelijke tabel die wordt gemaakt. Voor deze door de gebruiker gedefinieerde geschiedenistabel wordt een geclusterde columnstore-index en een extra niet-geclusterde rowstore-index (B-tree) gemaakt voor puntzoekacties. Nadat deze door de gebruiker gedefinieerde geschiedenistabel is gemaakt, wordt de tijdelijke tabel gemaakt waarin de door de gebruiker gedefinieerde geschiedenistabel wordt opgegeven als de standaardgeschiedenistabel.
Notitie
Documentatie maakt gebruik van de term B-tree in het algemeen in verwijzing naar indexen. In rijstore-indexen implementeert de database-engine een B+-boom. Dit geldt niet voor columnstore-indexen of indexen voor tabellen die zijn geoptimaliseerd voor geheugen. Zie de SQL Server- en Azure SQL-indexarchitectuur en ontwerphandleidingvoor meer informatie.
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));
Opmerkingen
Als u analysequery's wilt uitvoeren op de historische gegevens die gebruikmaken van statistische functies of vensterfuncties, wordt het maken van een geclusterde columnstore als primaire index ten zeerste aanbevolen voor compressie en queryprestaties.
Als u van plan bent tijdelijke tabellen te gebruiken voor gegevenscontrole (dat wil gezegd, zoeken naar historische wijzigingen voor één rij uit de huidige tabel), moet u een geschiedenistabel voor rijenopslag maken met een geclusterde index.
De geschiedenistabel kan geen primaire sleutel, refererende sleutels, unieke indexen, tabelbeperkingen of triggers hebben. Het kan niet worden geconfigureerd voor het vastleggen van wijzigingengegevens, het bijhouden van wijzigingen, transactionele replicatie of het samenvoegen van replicatie.
In Fabric SQL-database en in Azure SQL Database met Fabric-spiegeling geconfigureerd, wordt de bestaande tabel niet meer gespiegeld wanneer u een bestaande tabel gebruikt als de geschiedenistabel tijdens het maken van een tijdelijke tabel.
Een niet-tijdtabelfunctie wijzigen naar een systeemversiebeheerde tijdtabelfunctie.
U kunt systeemversiebeheer inschakelen voor een bestaande niet-tijdelijke tabel, bijvoorbeeld wanneer u een aangepaste tijdelijke oplossing wilt migreren naar ingebouwde ondersteuning.
U hebt bijvoorbeeld een set tabellen waarin versiebeheer wordt geïmplementeerd met triggers. Het gebruik van tijdelijke systeemversiebeheer is minder complex en biedt andere voordelen, waaronder:
- Onveranderbare geschiedenis
- Nieuwe syntaxis voor tijdreizende query's
- Betere DML-prestaties
- Minimale onderhoudskosten
Wanneer u een bestaande tabel converteert, kunt u overwegen de HIDDEN
-component te gebruiken om de nieuwe PERIOD
kolommen (de datetime2 kolommen ValidFrom
en ValidTo
) te verbergen om te voorkomen dat bestaande toepassingen die niet expliciet kolomnamen opgeven (bijvoorbeeld SELECT *
of INSERT
zonder een kolomlijst) niet zijn ontworpen om nieuwe kolommen te verwerken.
Versiebeheer toevoegen aan niet-tijdelijke tabellen
Als u wijzigingen wilt bijhouden voor een niet-tijdelijke tabel die de gegevens bevat, moet u de PERIOD
definitie toevoegen en eventueel een naam opgeven voor de lege geschiedenistabel die door SQL Server voor u wordt gemaakt:
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
Belangrijk
De precisie voor DATETIME2
moet overeenkomen met de precisie voor de onderliggende tabel.
Opmerkingen
Het toevoegen van niet-nullable kolommen met standaardwaarden aan een bestaande tabel met gegevens is een grootte van de gegevensbewerking voor alle andere edities dan SQL Server Enterprise Edition (waarop het een metagegevensbewerking is). Met een grote bestaande geschiedenistabel met gegevens in sql Server Standard-editie kan het toevoegen van een niet-null-kolom een dure bewerking zijn.
Beperkingen voor de begin- en eindkolommen van de periode moeten zorgvuldig worden gekozen:
De standaardinstelling voor de beginkolom geeft aan vanaf welk tijdstip bestaande rijen geldig moeten zijn. Het kan niet worden opgegeven als een datum/tijd-punt in de toekomst.
Eindtijd moet worden opgegeven als de maximumwaarde voor een bepaalde datum/tijd2 precisie, bijvoorbeeld
9999-12-31 23:59:59
of9999-12-31 23:59:59.9999999
.
Als u PERIOD
toevoegt, wordt een gegevensconsistentiecontrole uitgevoerd op de huidige tabel om ervoor te zorgen dat de bestaande waarden voor puntkolommen geldig zijn.
Wanneer een bestaande geschiedenistabel wordt opgegeven bij het inschakelen van SYSTEM_VERSIONING
, wordt een gegevensconsistentiecontrole uitgevoerd in zowel de huidige als de geschiedenistabel. U kunt deze overslaan als u DATA_CONSISTENCY_CHECK = OFF
opgeeft als extra parameter.
Bestaande tabellen migreren naar ingebouwde ondersteuning
In dit voorbeeld ziet u hoe u migreert van een bestaande oplossing op basis van triggers naar ingebouwde tijdelijke ondersteuning. In dit voorbeeld wordt ervan uitgegaan dat de huidige aangepaste oplossing de huidige en historische gegevens splitst in twee afzonderlijke gebruikerstabellen (ProjectTaskCurrent
en ProjectTaskHistory
).
Als uw bestaande oplossing gebruikmaakt van één tabel om werkelijke en historische rijen op te slaan, moet u de gegevens splitsen in twee tabellen voordat de migratiestappen in het volgende voorbeeld worden weergegeven. Verwijder eerst de trigger van de toekomstige temporele tabel. Controleer vervolgens of de PERIOD
kolommen niet nullbaar zijn.
/* 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
)
);
Opmerkingen
Als u verwijst naar bestaande kolommen in PERIOD
definitie, wordt impliciet generated_always_type
gewijzigd in AS_ROW_START
en AS_ROW_END
voor deze kolommen.
Als u PERIOD
toevoegt, wordt een gegevensconsistentiecontrole uitgevoerd op de huidige tabel om ervoor te zorgen dat de bestaande waarden voor puntkolommen geldig zijn.
We raden u ten zeerste aan om SYSTEM_VERSIONING
in te stellen met DATA_CONSISTENCY_CHECK = ON
, om consistentiecontroles voor gegevens af te dwingen op bestaande gegevens.
Als verborgen kolommen de voorkeur hebben, gebruikt u de opdracht ALTER TABLE [tableName] ALTER COLUMN [columnName] ADD HIDDEN;
.
Verwante inhoud
- tijdelijke tabellen
- Begin met systeem-geversioneerde temporele tabellen
- Het bewaren van historische gegevens in tijdelijke tabellen met systeemversies beheren
- Systeemversioneerde tijdbestanden met geheugen-geoptimaliseerde tabellen
- CREATE TABLE (Transact-SQL)
- gegevens wijzigen in een tijdelijke tabel met systeemversies
- Query uitvoeren op gegevens in een systeemversioneerde tijdtabieltabel
- het schema van een systeemversiebeheerde temporele tabel wijzigen
- systeemversiebeheer op een tijdelijke tabel met systeemversies stoppen