【发布时间】:2021-01-07 11:50:09
【问题描述】:
有没有办法从表中识别历史记录中删除的行?
所以当我执行更新或删除时,它会将数据移动到历史记录中,我想知道历史记录中的哪些行被删除了
帮助
【问题讨论】:
标签: sql sql-server tsql temporal-tables
有没有办法从表中识别历史记录中删除的行?
所以当我执行更新或删除时,它会将数据移动到历史记录中,我想知道历史记录中的哪些行被删除了
帮助
【问题讨论】:
标签: sql sql-server tsql temporal-tables
您可以使用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”的结构。应该包含您希望跟踪的所有列以及一个时间字段和一个 TypeField(删除、插入或更新)。
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)
基本上,我们正在查看 latest 版本为 no 的任何记录的主表和历史表(select * from Invoice FOR SYSTEM_TIME ALL)的联合更长时间有效 (MAX(SysEndTime) )
【讨论】: