SQL Server 2016:向现有应用程序添加时态表

car*_*reo 4 sql-server temporal-tables sql-server-2016

我有一个由外部公司开发的大型 PHP 应用程序,目前正在完成;我不能要求对其进行更改。它使用一个数据库 Microsoft SQL Server 2016,一些用户通过 SSMS 访问该数据库,包括我,以及在一天中的特定时间由一些计划任务访问。有时我会在一些表格中发现意想不到的内容,这很令人沮丧,因为我不知道它是什么时候到达的。我刚刚发现了时态表:知道记录更改的确切日期和时间将非常有用。

是否可以在应用程序中为 2-3 个关键表添加时态表,而无需更改 PHP 代码?是否存在兼容性或性能风险?

Sco*_*red 5

是否可以在应用程序中为 2-3 个关键表添加时态表,而无需更改 PHP 代码?

您应该能够实现该目标(假设应用程序的编写方式为向表中添加其他列不会导致问题)。当然,测试,测试,测试。

使用 Greg Larsen 的文章Altering an Existing Table to Support Temporal Data 中提供的示例代码 ,让我们来研究一个示例。

这是我们当前的表。

DROP TABLE IF EXISTS dbo.Product
DROP TABLE IF EXISTS dbo.ProductHistory

CREATE TABLE dbo.Product (
    ID INT Identity
    ,ProductName VARCHAR(50)
    ,ProductPrice DECIMAL(20, 2)
    );

INSERT INTO dbo.Product (ProductName, ProductPrice)
VALUES ('Widget',33.49),('Doo-Hickey',21.76),('Thing-A-Ma-Jig',20.16);

SELECT * FROM dbo.Product
Run Code Online (Sandbox Code Playgroud)
| ID | ProductName    | ProductPrice |
|----|----------------|--------------|
| 1  | Widget         | 33.49        |
| 2  | Doo-Hickey     | 21.76        |
| 3  | Thing-A-Ma-Jig | 20.16        |
Run Code Online (Sandbox Code Playgroud)

我们现在要跟踪版本。

为了开始为我的 dbo.Product 表收集历史信息,我需要更改该表以使其支持时态数据。SQL Server 2016 时态表需要一个表具有主键和一对日期​​/时间列。两个日期/时间列将用于确定记录有效的时间段。因此,我需要做的第一件事是更改我的 Product 表以满足时态数据表的要求。为此,我将运行以下代码:

ALTER TABLE dbo.Product 
    ADD CONSTRAINT PK_ProductID PRIMARY KEY (ID),
    BeginDate datetime2 GENERATED ALWAYS AS ROW START NOT NULL
        DEFAULT SYSUTCDATETIME()
,
    EndDate datetime2 GENERATED ALWAYS AS ROW END NOT NULL
        DEFAULT CAST('9999-12-31 23:59:59.9999999' AS datetime2),
    PERIOD FOR SYSTEM_TIME (BeginDate,EndDate);
Run Code Online (Sandbox Code Playgroud)

创建系统版本化临时表中有一些非常好的信息,该表解决了将非临时表更改为系统版本化临时表的问题。

转换现有表时,请考虑使用HIDDEN子句隐藏新的PERIOD列,以避免影响并非旨在处理新列的现有应用程序。


设置时态表的下一步是确定与我的 dbo.Product 表一起使用的历史表。为此,我将运行以下代码:

ALTER TABLE dbo.Product
        SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.ProductHistory));
Run Code Online (Sandbox Code Playgroud)

现在Product桌子看起来像这样

| ProductName    | ProductPrice | BeginDate                   | EndDate                     |
|----------------|--------------|-----------------------------|-----------------------------|
| Widget         | 33.49        | 2017-09-29 14:28:04.8327739 | 9999-12-31 23:59:59.9999999 |
| Doo-Hickey     | 21.76        | 2017-09-29 14:17:55.7149252 | 9999-12-31 23:59:59.9999999 |
| Thing-A-Ma-Jig | 20.16        | 2017-09-29 14:17:55.7149252 | 9999-12-31 23:59:59.9999999 |
Run Code Online (Sandbox Code Playgroud)

您还会发现ProductHistory已创建一个看起来与该Product表一模一样的新表。该ProductHistory表目前为空,因为我们尚未更新或删除 Product 表中的任何内容

现在,让我们运行更新以生成一些历史记录

UPDATE dbo.Product 
SET ProductPrice = 34.65
WHERE ProductName = 'Widget';

select * from dbo.Product
select * from dbo.Producthistory
Run Code Online (Sandbox Code Playgroud)

该product表有当前数据

| ProductName    | ProductPrice | BeginDate                   | EndDate                     |
|----------------|--------------|-----------------------------|-----------------------------|
| Widget         | 34.65        | 2017-09-29 14:35:49.7943164 | 9999-12-31 23:59:59.9999999 |
| Doo-Hickey     | 21.76        | 2017-09-29 14:35:41.8079586 | 9999-12-31 23:59:59.9999999 |
| Thing-A-Ma-Jig | 20.16        | 2017-09-29 14:35:41.8079586 | 9999-12-31 23:59:59.9999999 |
Run Code Online (Sandbox Code Playgroud)

现在该ProductHistory表有一个版本化的行

| ProductName | ProductPrice | BeginDate                   | EndDate                     |
|-------------|--------------|-----------------------------|-----------------------------|
| Widget      | 33.49        | 2017-09-29 14:35:41.8079586 | 2017-09-29 14:35:49.7943164 |
Run Code Online (Sandbox Code Playgroud)

您甚至可以向Product表格中添加一列,表格也会ProductHistory自动添加新列

ALTER TABLE dbo.Product ADD ProductColor VARCHAR(10)
Run Code Online (Sandbox Code Playgroud)

Product

| ProductName    | ProductPrice | BeginDate                   | EndDate                     | ProductColor |
|----------------|--------------|-----------------------------|-----------------------------|--------------|
| Widget         | 34.65        | 2017-09-29 14:35:49.7943164 | 9999-12-31 23:59:59.9999999 | NULL         |
| Doo-Hickey     | 21.76        | 2017-09-29 14:35:41.8079586 | 9999-12-31 23:59:59.9999999 | NULL         |
| Thing-A-Ma-Jig | 20.16        | 2017-09-29 14:35:41.8079586 | 9999-12-31 23:59:59.9999999 | NULL         |
Run Code Online (Sandbox Code Playgroud)

ProductHistory

| ProductName | ProductPrice | BeginDate                   | EndDate                     | ProductColor |
|-------------|--------------|-----------------------------|-----------------------------|--------------|
| Widget      | 33.49        | 2017-09-29 14:35:41.8079586 | 2017-09-29 14:35:49.7943164 | NULL         |
Run Code Online (Sandbox Code Playgroud)

是否存在兼容性或性能风险?

您当然需要先在开发环境中对此进行测试。您可能有一些独特的情况会影响您决定使用时态表。

以下是一些重要链接,其中包含有关时态表的其他信息

系统版本时态表入门

时态表注意事项和限制

管理系统版本化时态表中历史数据的保留

在系统版本控制的临时表上停止系统版本控制