问题描述
有没有办法从表中识别历史记录中已删除的行?
因此,当我执行更新或删除操作时,会将数据移动到历史记录中,我想知道历史记录中的哪些行被删除了
帮助
解决方法
您可以使用 output
子句。例如:
declare @ids table (id int);
delete from t
output deleted.id into @ids
where . . .;
select *
from @ids;
,
基于PK在时态表和历史表之间使用半反连接。
,举个例子...
CREATE SCHEMA _CHRONO;
GO
CREATE TABLE dbo.TEMPO
(
ID INT IDENTITY PRIMARY KEY,SOME_DATA VARCHAR(32),_DH_DEB DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,_DH_FIN DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,PERIOD FOR SYSTEM_TIME (_DH_DEB,_DH_FIN)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = _CHRONO.TEMPO));
GO
INSERT INTO dbo.TEMPO VALUES ('a data'),('another data')
GO
DELETE FROM dbo.TEMPO WHERE SOME_DATA LIKE '%other%'
GO
现在查询检索已删除的行:
SELECT CT.*
FROM _CHRONO.TEMPO AS CT
LEFT OUTER JOIN dbo.TEMPO AS T
ON CT.ID = T.ID
获取删除行的最后一个版本需要添加一些额外的SQL条件
,如果你想知道历史记录中删除了哪些行,只需创建一个审计表并在真实表中设置一个触发器即可。
例如,您有一个名为“PeopleTbl”的表。
1- 您将创建一个审计表来存储“PeopleTbl”的历史记录。让我们创建一个名为“PeopleAuditTbl”的表。
“PeopleAuditTbl”的结构。应该包含您希望跟踪的所有列、时间字段和类型字段(删除、插入或更新)。
2- 现在在您的“PeopleTbl”中。您将创建一个触发器来存储更新或删除(如果需要,您也可以存储插入的记录。
删除触发器应该是这样的。
ALTER TRIGGER T_PeopleTbl
ON PeopleTbl
AFTER DELETE
AS
INSERT INTO PeopleAuditTbl(
//Fields you want to store
Date,TypeField
)
SELECT
//Fields you want to store
GETDate(),'DELETE'
FROM DELETED
,
如果您希望使用 Temporal History 表来识别已从 Main 表中删除的记录,以下示例演示了如何实现:
-- Create a Temporal Table for demonstration purposes
CREATE TABLE dbo.Invoice
(
InvoiceId int identity(1,1) PRIMARY KEY CLUSTERED,InvoiceDate date NOT NULL
-- Other fields...,SysStartTime datetime2 GENERATED ALWAYS AS ROW START,SysEndTime datetime2 GENERATED ALWAYS AS ROW END,PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.InvoiceHistory));
go
-- Create some dummy data
insert into Invoice(InvoiceDate) values ('2020-01-01'),('2020-02-01')
go
WAITFOR DELAY '00:00:03'
go
delete from Invoice where InvoiceId=1
go
-- Get Current Records
select * from Invoice
-- Get Deleted Records
;with cte as
(
select InvoiceId,MAX(SysEndTime) [SysEndTime]
from Invoice FOR SYSTEM_TIME ALL
group by InvoiceId
having MAX(SysEndTime) < '9999-12-31'
)
select i.*
from Invoice FOR SYSTEM_TIME ALL i
inner join cte c on (i.InvoiceId=c.InvoiceId and i.SysEndTime=c.SysEndTime)
基本上,我们正在查看主表和历史表的联合(select * from Invoice FOR SYSTEM_TIME ALL)以获取最新版本不存在的任何记录更长的有效时间 (MAX(SysEndTime) )