ある日付範囲の監査情報を提供するストアド プロシージャを作成しようとしています。監査テーブルには、監査日、列名、および古い値が格納されます。結果セットに古い値と新しい値を表示したいと考えています。次の最新の監査エントリまたはエンティティ自体から新しい値を取得する必要があります。ストアド プロシージャは、必要な結果セットを取得するための多段階アプローチです。
- 日付範囲内の監査レコードを含む @results 一時テーブルを作成します。
- エンティティからの現在の値で @currentValues 一時テーブルを作成します。
- @results テーブルを更新して新しい値を保存する
監査テーブルの構造は次のとおりです。
- AuditId 一意の識別子 NEWID()
- AuditDate 日時 GETDATE()
- UserId 一意の識別子
- EntityId 一意の識別子
- 列名 nvarchar(100)
- OldValue 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 を設定する必要があります。 @Results は、NewValue に設定された値である必要があります。これを試してみましたが、サブクエリで Order By を使用できないというエラーが表示されます。これを行う別の方法はありますか?どんな提案も歓迎しますが、結果に何千行もある可能性があるため、パフォーマンスを考慮する必要があります。
- 編集
これを機能させる方法の 1 つを次に示しますが、これが最適なパフォーマンスかどうかはわかりません。
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