制作一个“普通”表作为临时表

问题描述

我有一个这样创建的表:

CREATE TABLE address_user 
(
    [username] VARCHAR(13) NOT NULL,[address] CHAR(58) NOT NULL,[id] BIGINT NOT NULL,CONSTRAINT [PK_ address_user] 
        PRIMARY KEY CLUSTERED ([id] ASC)
);

现在我希望能够保留这个表的历史修改,所以我想把它做成临时表。我知道创建临时表的脚本,最终结果应该是:

CREATE TABLE address_user 
(
    [username] VARCHAR(13) NOT NULL,[sys_start_time] DATETIME2(7) 
        GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,[sys_end_time] DATETIME2 (7) 
        GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,PERIOD FOR SYstem_TIME ([sys_start_time],[sys_end_time]),CONSTRAINT [PK_ address_user] 
        PRIMARY KEY CLUSTERED ([id] ASC)
)
WITH (SYstem_VERSIONING = ON (HISTORY_TABLE=[dbo].[address_user_history],DATA_CONSISTENCY_CHECK=ON));

最简单的方法就是删除之前的表,然后重新创建具有良好架构的表。

然而,我的表中有很多信息,保存数据并删除表,重新创建并重新插入数据让我感到不舒服。

因此,如果您有一个解决方案可以转换时态表中的第一个表,而无需删除所有内容并重新创建它,那应该会很有帮助!

解决方法

创建新表address_user_new,插入数据,然后使用sp_renameaddress_user重命名为address_user_old,将address_user_new重命名为address_user。这一切都可以在事务中完成,以确保转换是原子的且明显是瞬时的。例如

if object_id('address_user') is not null
  ALTER TABLE address_user SET ( SYSTEM_VERSIONING = OFF)
go
if object_id('address_user_new') is not null
  ALTER TABLE address_user_new SET ( SYSTEM_VERSIONING = OFF)
go
drop table if exists address_user
drop table if exists address_user_history
drop table if exists address_user_new
drop table if exists address_user_old
go

CREATE TABLE address_user 
(
    [username] VARCHAR(13) NOT NULL,[address] CHAR(58) NOT NULL,[id] BIGINT NOT NULL,CONSTRAINT [PK_address_user] 
        PRIMARY KEY CLUSTERED ([id] ASC)
);

go
CREATE TABLE address_user_new 
(
    [username] VARCHAR(13) NOT NULL,[sys_start_time] DATETIME2(7) 
        GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,[sys_end_time] DATETIME2 (7) 
        GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,PERIOD FOR SYSTEM_TIME ([sys_start_time],[sys_end_time]),CONSTRAINT [PK_address_user_new] 
        PRIMARY KEY CLUSTERED ([id] ASC)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[address_user_history],DATA_CONSISTENCY_CHECK=ON));

go


set xact_abort on
begin transaction

insert into address_user_new(username,address,id)
select username,id
from address_user with (tablockx)

exec sp_rename 'address_user','address_user_old','OBJECT'
exec sp_rename 'PK_address_user','PK_address_user_old','OBJECT'

exec sp_rename 'address_user_new','address_user','OBJECT'
exec sp_rename 'PK_address_user_new','PK_address_user','OBJECT'

commit transaction