将 GENERATED ALWAYS 列更改为 GENERATED BY DEFAULT 标识列 - Sql Server

问题描述 投票:0回答:2

我需要将配置为

GENERATED ALWAYS
的现有表列更改为
GENERATED BY DEFAULT

表结构示例

CREATE TABLE [dbo].[Contact](
    [ContactID] [uniqueidentifier] NOT NULL,
    [ContactNumber] [nvarchar](50) NOT NULL,
    [SequenceID] [int] IDENTITY(1,1) NOT NULL,
    [SysStartTime] [datetime2](0) GENERATED ALWAYS AS ROW START NOT NULL,
    [SysEndTime] [datetime2](0) GENERATED ALWAYS AS ROW END NOT NULL,
 CONSTRAINT [PK_Contact] PRIMARY KEY NONCLUSTERED 
(
    [ContactID] ASC
)WITH (PAD_INDEX = OFF, 
       STATISTICS_NORECOMPUTE = OFF, 
       IGNORE_DUP_KEY = OFF, 
       ALLOW_ROW_LOCKS = ON, 
       ALLOW_PAGE_LOCKS = ON) 
   ON [PRIMARY],
PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime])
) ON [PRIMARY]
WITH
(
    SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ContactHistory],
                            DATA_CONSISTENCY_CHECK = ON )
)

这是我已经拥有的表格,现在我需要更改列

[SysStartTime]
GENERATED BY DEFAULT
GENERATED ALWAYS

我尝试了以下代码

ALTER TABLE dbo.Contact ALTER column SysStartTime SET GENERATED BY DEFAULT

但是它抛出了一个错误

消息 156,级别 15,状态 1,第 19 行关键字附近的语法不正确 ‘设置’。

请帮助我。

sql-server sql-server-2016 alter-table temporal-database
2个回答
1
投票

我知道这是一个老问题,但我偶然发现了一个类似的问题,并且我找到了一种方法来实现与此处所需的结果相同的最终结果(让记录讲述其创建时间的正确故事,并正确地与时间查询)。

我所做的是:

  1. 创建了两个表(主表及其历史记录)
  2. 用其数据加载主表
  3. 更新了主表中的所有记录,但不更改任何数据。这会导致在历史表中创建等效记录
  4. 使用
    ALTER TABLE Contact SET (SYSTEM_VERSIONING = OFF);
  5. 禁用表中的系统版本控制
  6. 更新了历史记录表中的 ValidFrom 字段,以正确反映最初实际插入记录的日期。 (只有禁用表的系统版本控制才能执行此操作)
  7. 使用
    ALTER TABLE Contact SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ContactHistory], DATA_CONSISTENCY_CHECK = ON ))
  8. 重新启用表中的系统版本控制

这会导致记录相同(除了 ValidFrom/To 字段),但允许使用

FOR SYSTEM_TIME AS OF 'YYYY-MM-DD THH:mm:SS.0000000';
的任何查询正常工作并准确地表示请求时刻的数据。

尝试此操作时我发现的事情:

  • 您无法将现有字段更改为
    GENERATED ALWAYS AS ROW START/END
    。它需要是一个从一开始就这样设置的字段。
  • 您不能将 DATETIMEOFFSET 字段用于周期字段。
  • 无法设置主表中周期字段的值
  • 如果启用版本控制,则无法操作历史表中的数据

附加文档: https://learn.microsoft.com/en-us/sql/relational-databases/tables/querying-data-in-a-system-versioned-temporal-table?view=sql-server-ver15


0
投票

虽然这不是这个老问题的直接答案,但我遇到了 Kelps Sousa Alux 提到的一个问题,我需要在开始时不“始终生成”一个表列,以便我可以明确地插入 ValidFrom/To 值,但在一系列其他操作之后,这些列需要最终成为“始终生成”。

虽然不是直接的,但可以这样做

首先分别创建一个表和历史表,插入所需的数据,然后添加 PERIOD FOR SYSTEM_TIME,如果需要,将列设置为隐藏,然后设置系统版本控制。

CREATE TABLE Test (
    ID IDENTITY(1,1) PRIMARY KEY NOT NULL,
    Value VARCHAR(10),
    ValidFrom DATETIME2 DEFAULT(GETUTCDATE()) NOT NULL,
    ValidTo DATETIME2 DEFAULT(CONVERT[DATETIME2], '9999-12-31 23:59:59.999') NOT NULL
);

CREATE TABLE TestHistory (
    ID IDENTITY(1,1) PRIMARY KEY NOT NULL,
    Value VARCHAR(10),
    ValidFrom DATETIME2 NOT NULL,
    ValidTo DATETIME2 NOT NULL
);
GO

-- At this point, you can insert data explicitly for all columns

ALTER TABLE Test ADD PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
GO

ALTER TABLE Test ALTER COLUMN ValidFrom ADD HIDDEN;
ALTER TABLE Test ALTER COLUMN ValidTo ADD HIDDEN;
GO

ALTER TABLE Test SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.TestHistory))

如果您需要禁用时态表,将数据显式插入到所有列,然后将历史表重新附加到时态表,您也可以这样做 - 像这样:

ALTER TABLE Test SET (SYSTEM_VERSIONING = OFF);
GO

ALTER TABLE Test DROP PERIOD FOR SYSTEM_TIME;
GO

-- At this point, you can insert data explicitly into all columns
GO

ALTER TABLE Test ADD PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
ALTER TABLE Test SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.TestHistory))
GO

ALTER TABLE Test ALTER COLUMN ValidFrom ADD HIDDEN;
ALTER TABLE Test ALTER COLUMN ValidTo ADD HIDDEN;
GO

如果需要,请记住身份插入。

© www.soinside.com 2019 - 2024. All rights reserved.