我正在尝试编写一个存储过程,它将为我提供日期范围之间的审计信息。审计表存储审计日期、列名和旧值。我想在结果集中显示旧值和新值。我需要从下一个最近的审计条目或从实体本身获取新值。存储过程是获取我需要的结果集的多步骤方法。
- 使用日期范围内的审计记录创建一个 @results 临时表。
- 使用来自实体的当前值创建一个 @currentValues 临时表。
- 更新@results 表以存储新值
这是审计表的结构:
- AuditId 唯一标识符 NEWID()
- AuditDate 日期时间 GETDATE()
- 用户 ID 唯一标识符
- EntityId 唯一标识符
- 列名 nvarchar(100)
- 旧值 nvarchar(MAX)
这是sql:
CREATE PROC GetAuditSummary
@StartDate datetime = NULL,
@EndDate datetime = NULL
AS
DECLARE @Results table(
AuditId uniqueidentifier,
AuditDate datetime,
UserId uniqueidentifier,
EndityId uniqueidentifier,
ColumnName nvarchar(100),
OldValue nvarchar(MAX),
NewValue nvarchar(MAX)
INSERT INTO @Results(AuditId, AuditDate, UserId, EntityId, ColumnName, OldValue)
SELECT AuditId, AuditDate, UserId, EntityId, ColumnName, OldValue
FROM Audit
WHERE (AuditDate >= @StartDate) AND (AuditDate < @EndDate)
DECLARE @CurrentValues table(
EntityId uniqueidentifier,
ColumnName nvarchar(100),
Value nvarchar(MAX)
)
--Lengthy Code to fill @CurrentValues temp table. Assume @CurrentValues is populated
UPDATE @Results
SET NewValue = n.Value
FROM @Results r INNER JOIN
(SELECT AUditId, AuditDate, EntityId, ColumnName, OldValue AS Value
FROM Audit
UNION ALL
SELECT NULL, GETDATE(), EntityId, ColumnName, Value
FROM @CurrentValues
ORDER BY AuditDate DESC
) n ON n.EntityId = r.EntityId AND
n.ColumnNmae = r.ColumName NAD
n.AuditDate > r.AuditDate
SELECT * FROM @Results ORDER BY AuditDate DESC
现在,如果我错了,请纠正我,当更新语句执行时,NewValue 应该设置为连接结果集中的最后一个匹配行,并且由于我有由 AuditDate 排序的子查询,AuditDate 最接近当前记录@Results 应该是设置为 NewValue 的值。我已经尝试过了,但是我收到一个错误消息,告诉我不能在子查询中使用 Order By。还有另一种方法可以做到这一点吗?我愿意接受任何建议,但我需要考虑性能,因为结果中可能会有数千行。
- 编辑
这是使其工作的一种方法,但我不确定它是否是性能上最好的。
UPDATE @Results
SET NewValue = COALESCE(
(SELECT TOP 1 a.OldValue
FROM Audit a
WHERE (a.EntityId = r.EntityId) AND
(a.ColumnName = r.ColumnName) AND
(a.AuditDate > r.AuditDate)
ORDER BY a.AuditDate),
(SELECT TOP 1 c.Value
FROM @CurrentValues c
WHERE (c.EntityId = r.EntityId) AND
(c.ColumnName = r.ColumnName))
FROM @Results r