使用触发器在SQL Server 2008中保存更新的列

时间:2011-09-06 15:29:29

标签: sql-server tsql triggers

我在数据库中有一个大表,我想跟踪对各个记录所做的更改。更确切地说,我想记录日期和对列的更改。

由于该表有25个以上的comlumns,我不想单独测试它们。

日志记录表看起来像ID-Date-Table-Column-OldValue-NewValue

在我的AFTER UPDATE触发器中,我想检查哪些列具有不同的值并将其记录到我的表中。

我知道我可以通过以下方式获取表格的列:

DECLARE @meta_table TABLE (  
    idx smallint Primary Key IDENTITY(1,1) 
    , TABLE_NAME nchar(100), COLUMN_NAME nchar(100), COLUMN_ID int 
) 

INSERT @meta_table 
SELECT TABLE_NAME, COLUMN_NAME,
    COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME),
    COLUMN_NAME, 'ColumnID') AS COLUMN_ID
FROM MYDATABASE.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable';

我可以使用:

迭代列
SET @i = 1 
SET @numrows = (SELECT COUNT(*) FROM @meta_table) 
IF @numrows > 0 
    WHILE (@i <= (SELECT MAX(idx) FROM @meta_table)) 
    BEGIN 
        SET @col = (SELECT COLUMN_NAME FROM @meta_table WHERE idx = @i)

        -- do something with @col

        SET @i = @i + 1 
    END

在第一步中,我想检查所有列,但这样的东西不起作用

IF (SELECT @col FROM inserted) <> (SELECT @col FROM deleted)
BEGIN
    -- INSERT into logging table ...
END

此外,它只会检查第一行更新,因此我需要对已删除/插入的表中的每一行执行此操作。

3 个答案:

答案 0 :(得分:2)

迭代表列没有意义。由于触发器是针对特定表的,因此您已经知道它具有哪些列!只需使用您感兴趣的列对触发器进行编码。您说这可能是一个重复的,无聊的,容易出错的任务吗?在这种情况下,优秀的程序员可以自动执行任务,例如。求助于代码生成自动生成触发器,立即重构它们并使它们与架构更改保持同步。部署运行时模式发现不是可行的方法。

答案 1 :(得分:1)

Change Data Capture可以是日志表DML更改的解决方案。

答案 2 :(得分:0)

嗯 - 如果您只想记录已更改的字段,那么您肯定需要单独检查每个字段。但是,正如您所发现的,比较在不同的数据类型上不起作用。因此,您可能需要检查每个字段的数据类型,并相应地进行比较。我相信在INFORMATION_SCHEMA中有一个名为'DATA_TYPE'的字段,因此当您执行元表插入时,添加其他列:


INSERT @meta_table  
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE,
    COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), 
    COLUMN_NAME, 'ColumnID') AS COLUMN_ID 
FROM MYDATABASE.INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'myTable'; 


然后在循环中检查它:


SET @i = 1    
SET @numrows = (SELECT COUNT(*) FROM @meta_table)    
IF @numrows > 0    
    WHILE (@i <= (SELECT MAX(idx) FROM @meta_table))    
    BEGIN    
        SELECT @col = COLUMN_NAME, @dataType = DATA_TYPE
        FROM @meta_table WHERE idx = @i)   

        -- do something with @col   

        SET @i = @i + 1    
    END   

然后在进行比较之前先检查数据类型。


IF(@dataType = 'varchar')
BEGIN

-- do your comparison and insert here

END
ELSE IF(@dataType = 'int')
BEGIN

-- do you comparison and insert here

END
....



...依此类推,对于表格中的所有不同数据类型......