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

Sql server 使用触发器在SQL Server 2008中保存更新的列,sql-server,tsql,triggers,Sql Server,Tsql,Triggers,我在数据库中有一个大表,我想跟踪对单个记录所做的更改。更准确地说,我想记录日期和对列所做的更改 因为这个表有25个以上的组件,所以我不想单独测试它们 日志记录表看起来像ID日期表列OldValue NewValue 在更新后的触发器中,我想检查哪些列具有不同的值,并将它们记录到我的表中 我知道我可以通过以下方式获得表中的列: DECLARE @meta_table TABLE ( idx smallint Primary Key IDENTITY(1,1) , TABLE_

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

因为这个表有25个以上的组件,所以我不想单独测试它们

日志记录表看起来像
ID日期表列OldValue NewValue

在更新后的
触发器中,我想检查哪些列具有不同的值,并将它们记录到我的表中

我知道我可以通过以下方式获得表中的列:

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
SET@i=1
设置@numrows=(从@meta_表中选择COUNT(*)
如果@numrows>0

虽然(@iHmm-如果您只想记录已更改的字段,那么您肯定需要分别检查每个字段。但是,正如您所发现的,比较在不同的数据类型上并不相同。因此,您可能需要检查每个字段的数据类型,并进行相应的比较。我相信有一个字段名为'D'信息模式中的ATA_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   

…等等,对于表中所有不同的数据类型…

嗯-如果您只想记录已更改的字段,那么您肯定需要分别检查每个字段。但是,正如您所发现的,比较在不同的数据类型上不起作用。因此,您可能需要检查每个字段的数据类型我相信在信息模式中有一个名为“DATA\u 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   

…等等,对于表中的所有不同数据类型…

可以是记录表DML更改的解决方案。

可以是记录表DML更改的解决方案。

在表列上迭代没有意义。因为触发器是针对特定表的,所以您已经知道它有哪些列了!只需用t对触发器进行编码即可他是你感兴趣的专栏。你说这可能是一项重复、枯燥、容易出错的任务?在这种情况下,优秀的程序员会自动完成任务,例如,借助代码生成自动生成触发器,在瞬间重构触发器,并使其与架构更改保持同步。部署运行时架构发现不是一条可行之路。

对表列进行迭代没有意义。因为触发器是针对特定表的,所以您已经知道它有哪些列了!只需使用您感兴趣的列对触发器进行编码。您说这可能是一项重复的、枯燥的、容易出错的任务?在这种情况下,优秀的程序员会自动完成任务,例如,求助于代码生成to自动生成触发器,立即对其进行重构,并使其与架构更改保持同步。部署运行时架构发现不是一个好办法。

Hmm-因此,我猜您也希望对多行执行此操作,在update语句修改了多行的情况下-在这种情况下,您需要用光标选择所有修改的行ws,然后检查每一行…嗯-我猜您也希望对多行执行此操作,在update语句修改了多行的情况下-在这种情况下,您需要用光标选择所有修改的行,然后检查每一行…您查看了列_UPDATED()了吗?您查看了列_UPDATED()了吗?列不受我的控制,可以随时添加/删除,因此我必须在运行时获取列。列不受我的控制,可以随时添加/删除,因此我必须在运行时获取列。