Sistem sürümüne sahip bir zamana bağlı tablodaki verileri değiştirme

Şunlar için geçerlidir: SQL Server 2016 (13.x) ve sonraki sürümler Azure SQL VeritabanıAzure SQL Yönetilen ÖrneğiSQL database in Microsoft Fabric

Sistem sürümüne sahip bir zamana bağlı tablodaki veriler normal veri işleme dili (DML) deyimleri kullanılarak değiştirilir ve önemli bir fark vardır: dönem sütunu verileri doğrudan değiştirilemez. Veri güncellendiğinde, sürüm güncellenir ve her güncellenmiş satırın önceki sürümü geçmiş tablosuna eklenir. Veri silindiğinde, silme mantıklıdır ve satır mevcut tablodan geçmiş tablosuna taşınır; Veriler kalıcı olarak silinmiyor.

Veri ekleme

Yeni veri eklediğinizde, PERIODdeğilse HIDDEN sütunlarını hesaba eklemeniz gerekir. Zamansal tablolarla bölüm değiştirme özelliğini de kullanabilirsiniz.

Görünür dönem sütunlarıyla yeni veri girme

INSERT ifadenizi, görünür PERIOD sütunları dikkate alacak şekilde aşağıdaki gibi oluşturun:

INSERT deyiminizde sütun listesini belirtirseniz, sistem bu sütunlar için değerleri otomatik olarak oluşturduğundan PERIOD sütunlarını atlayabilirsiniz.

-- Insert with column list and without period columns
INSERT INTO [dbo].[Department]
(
    [DeptID],
    [DeptName],
    [ManagerID],
    [ParentDeptID]
)
VALUES (10, 'Marketing', 101, 1);

PERIOD deyiminizde sütun listesindeki INSERT sütunlarını belirtirseniz, değerleri olarak DEFAULT belirtmeniz gerekir.

INSERT INTO [dbo].[Department]
(
    DeptID,
    DeptName,
    ManagerID,
    ParentDeptID,
    ValidFrom,
    ValidTo
)
VALUES (11, 'Sales', 101, 1, DEFAULT, DEFAULT);

INSERT deyiminizde sütun listesini belirtmezseniz, DEFAULT sütunlar için PERIOD belirtin.

-- Insert without a column list and DEFAULT values for period columns
INSERT INTO [dbo].[Department]
VALUES (
    12,
    'Production',
    101,
    1,
    DEFAULT,
    DEFAULT
);

Gizli dönem sütunları içeren bir tabloya veri ekleme

PERIOD sütunlar HIDDENolarak belirtilirse, PERIOD ifadenizde INSERT sütunlarını hesaba katmanıza gerek yoktur. Bu davranış, sürüm oluşturmadan yararlanan tablolarda sistem sürümü oluşturmayı etkinleştirdiğinizde eski uygulamalarınızın çalışmaya devam etmesi garanti eder.

CREATE TABLE [dbo].[CompanyLocation]
(
    [LocID] INT IDENTITY (1, 1) NOT NULL PRIMARY KEY,
    [LocName] VARCHAR (50) NOT NULL,
    [City] VARCHAR (50) NOT NULL,
    [ValidFrom] DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,
    [ValidTo] DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
    PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo])
)
WITH (SYSTEM_VERSIONING = ON);
GO

INSERT INTO [dbo].[CompanyLocation]
VALUES ('Headquarters', 'New York');

PARTITION SWITCH kullanarak veri ekleme

Mevcut tablo bölümlenmişse, verileri verimli bir şekilde boş bir bölüme yüklemek veya paralel olarak birden fazla bölüme yüklemek için kullanılabilir PARTITION SWITCH .

Zamansal tabloyla birlikte kullanılan PARTITION SWITCH IN deyimindeki hazırlama tablosunda SYSTEM_TIME PERIOD tanımlanmış olmalıdır, ancak bunun zamansal bir tablo olması gerekmez. Bu, hazırlama tablosuna veri ekleme sırasında veya önceden doldurulmuş bir hazırlama tablosuna SYSTEM_TIME süre eklendiğinde zamansal tutarlılık denetimlerinin gerçekleştirilmesini sağlar.

/* Create staging table with period definition for SWITCH IN temporal table */
CREATE TABLE [dbo].[Staging_Department_Partition2]
(
    [DeptID] INT NOT NULL,
    [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])
) ON [PRIMARY];

/* Create aligned primary key */
ALTER TABLE [dbo].[Staging_Department_Partition2]
    ADD CONSTRAINT [Staging_Department_Partition2_PK]
        PRIMARY KEY CLUSTERED ([DeptID] ASC) ON [PRIMARY];

/*
Create and enforce constraints for partition boundaries.
Partition 2 contains rows with DeptID > 100 and DeptID <=200
*/
ALTER TABLE [dbo].[Staging_Department_Partition2] WITH CHECK
    ADD CONSTRAINT [chk_staging_Department_partition_2]
            CHECK ([DeptID] > N'100' AND [DeptID] <= N'200');

ALTER TABLE [dbo].[Staging_Department_Partition2]
    CHECK CONSTRAINT [chk_staging_Department_partition_2];

/*Load data into staging table*/
INSERT INTO [dbo].[staging_Department] (
    [DeptID],
    [DeptName],
    [ManagerID],
    [ParentDeptID]
)
VALUES (101, 'D101', 1, NULL);

/*Use PARTITION SWITCH IN to efficiently add data to current table */
ALTER TABLE [Staging_Department]
    SWITCH TO [dbo].[Department] PARTITION 2;

Bir tablodan dönem tanımı olmadan PARTITION SWITCH gerçekleştirmeye çalışırsanız bir hata iletisi alırsınız.

Msg 13577, Level 16, State 1, Line 25 ALTER TABLE SWITCH statement failed on table 'MyDB.dbo.Staging_Department_2015_09_26' because target table has SYSTEM_TIME PERIOD while source table does not have it.

Verileri güncelleştirme

Geçerli tablodaki verileri normal bir UPDATE deyimiyle güncelleştirirsiniz. Felaket senaryosu için geçmiş tablodan mevcut tablodaki verileri güncelleyebilirsiniz. Ancak, PERIOD sütunlarını güncelleştiremez ve SYSTEM_VERSIONING = ONgeçmiş tablosundaki verileri doğrudan güncelleştiremezsiniz.

SYSTEM_VERSIONINGOFF olarak ayarlayıp geçerli ve geçmiş tablolarındaki satırları güncellerseniz, sistem değişikliklerin geçmişini korumaz.

Geçerli tabloyu güncelleştirme

Bu örnekte, ManagerIDDeptIDolduğu her satır için 10 sütunu güncelleştirilir. PERIOD sütunlarına hiçbir şekilde başvurulmuyor.

UPDATE [dbo].[Department]
SET [ManagerID] = 501
WHERE [DeptID] = 10;

Ancak, PERIOD sütununu güncelleştiremez ve geçmiş tablosunu güncelleştiremezsiniz. Bu örnekte, bir PERIOD sütununu güncelleştirme girişimi bir hata oluşturur.

UPDATE [dbo].[Department]
    SET ValidFrom = '2015-09-23 23:48:31.2990175'
WHERE DeptID = 10;

ifade aşağıdaki hatayı oluşturur.

Msg 13537, Level 16, State 1, Line 3
Cannot update GENERATED ALWAYS columns in table 'TmpDev.dbo.Department'.

Geçerli tabloyu, geçmiş tablosundan güncelleştir

Geçerli tablodaki UPDATE kullanarak gerçek satır durumunu geçmişte belirli bir noktada geçerli bir duruma döndürebilirsiniz. Bunu, son iyi bilinen satır sürümünegeri dönmek olarak düşünün. Aşağıdaki örnek, 25 Nisan 2015 itibarıyla, DeptID'ün 10 olduğu duruma göre geçmiş tablosundaki değerlere geri dönüldüğünü göstermektedir.

UPDATE Department
SET DeptName = History.DeptName
FROM Department FOR SYSTEM_TIME
    AS OF '2015-04-25' AS History
WHERE History.DeptID = 10
    AND Department.DeptID = 10;

Verileri sil

Geçerli tablodaki verileri normal bir DELETE deyimiyle silersiniz. Silinen satırların bitiş dönemi sütunu, temel alınan işlemin başlangıç saatiyle doldurulur. SYSTEM_VERSIONING ONiken geçmiş tablosundaki satırları doğrudan silemezsiniz. SYSTEM_VERSIONING = OFF ayarlar ve geçerli ve geçmiş tablolarındaki satırları silerseniz, sistem değişikliklerin geçmişini korumaz.

SYSTEM_VERSIONING = ONsırasında aşağıdaki ifadeler desteklenmiyor:

  • TRUNCATE
  • Geçerli tablo için SWITCH PARTITION OUT
  • Geçmiş tablosu için SWITCH PARTITION IN

Zamana bağlı tablodaki verileri değiştirmek için kullanın MERGE

MERGE işlemi, INSERT sütunlarıyla ilgili olarak, UPDATE ve PERIOD deyimlerinin sahip olduğu aynı sınırlamalarla desteklenir.

CREATE TABLE DepartmentStaging
(
    DeptId INT,
    DeptName VARCHAR (50)
);
GO

INSERT INTO DepartmentStaging
VALUES (1, 'Company Management');

INSERT INTO DepartmentStaging
VALUES (10, 'Science & Research');

INSERT INTO DepartmentStaging
VALUES (15, 'Process Management');

MERGE INTO dbo.Department AS target
USING (
    SELECT DeptId, DeptName
    FROM DepartmentStaging
    ) AS source(DeptId, DeptName)
    ON (target.DeptId = source.DeptId)
WHEN MATCHED
    THEN UPDATE SET DeptName = source.DeptName
WHEN NOT MATCHED
    THEN
        INSERT (DeptId, DeptName)
        VALUES (source.DeptId, source.DeptName);