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)

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

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

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

系统版本时态表入门

时态表注意事项和限制

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

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