SQL 服务器触发器从存储过程动态更新日志列

SQL Server trigger to Log columns updated from a stored procedure dynamically

我有一个存储过程,它在执行时会在单个 table 中更新约 100 列。

我想在受影响的 table 上创建一个触发器,它将:

  1. 确定所有(实际)更新的值 (所以如果新值为'1',旧值为'1',则忽略)

  2. 从实际变化值列表中,得到列名和数据值

  3. 获取列名和旧数据值并通过插入将它们存储到日志中table (INSERT ColumnName, Value INTO LogTable)

我有一个可行的解决方案,但我必须创建一个临时文件 table 并在临时文件 table 中为我知道受影响的每一列插入一行......就像拥有其中的 100 个:

INSERT INTO @TempTable (
ID,
ColumnName,
OldColumnValue
)
SELECT i.ID, 'Column1', i.Column1
FROM inserted i 
INNER JOIN deleted d ON d.ID = i.ID
WHERE COALESCE(d.Column1, '') != COALESCE(i.Column1, '')

在为 column1 一直插入到 column100 之后,我只需将 @TempTable 中的所有记录插入到日志中 table。

必须有更动态的方法来解决这个问题,但我想不出。

*为了简单起见,假设值将始终为 [TEXT],LogTable 中的值也将如此。

没有您的 table 定义,我无法完整回答这个问题,但是,您在这里需要做的是对所有数据进行逆透视,然后当值不等于另一个时,将其插入您的日志 table。这意味着您的查询需要如下所示:

INSERT INTO dbo.LogTable (ID,
                          ColumnName,
                          OldColumnValue)
SELECT d.ID,
       V.ColumnName,
       V.OldColumnValue
FROM deleted d
     JOIN inserted i ON d.ID = i.ID
     CROSS APPLY (VALUES(N'Column1',i.Column1, d.Column1),
                        (N'Column2',i.Column2, d.Column2),
                        (N'Column3',i.Column3, d.Column3),
                        (N'Column4',i.Column4, d.Column4))V(ColumnName, NewColumnValue, OldColumnValue)
WHERE V.NewColumnValue != V.OldColumnValue
   OR (V.NewColumnValue IS NULL AND V.OldColumnValue IS NOT NULL)
   OR (V.NewColumnValue IS NOT NULL AND V.OldColumnValue IS NULL);

但是请注意,列必须由相同的数据类型组成,我怀疑您的所有列都是相同的数据类型。因此,您将需要明确地将所有列 CONVERT 设为 (n)varchar。对于日期和时间值的列,我强烈建议您也使用显式 CONVERT 中的样式代码;像 112 代表 date,也许 126 代表其他日期和时间数据类型。