如何有效地阻止对触发器中除一列之外的所有列的更新?

时间:2011-11-24 06:28:45

标签: sql sql-server tsql

我有一个包含250列的表,我必须在其上编写一个触发器,它将阻止对除一列之外的所有列的更新。

有一个可以更新的列evt_updatable。触发器的责任是当用户尝试更新此列以外的任何内容时引发错误。

实现这一目标的不同方法有哪些。 一种方法是声明500个存储插入和删除值的变量。如下面的代码片段所示。

SELECT         @newColdata1              = i.col1
               @oldColdata1              = d.col1
               @newColdata2              = i.col2
               @oldColdata2              = d.col1
                  ----------------------------
                ------------------------------ -- same thing for remaining 250 rows
     FROM      inserted i, deleted d
     WHERE     i.evt_code = d.evt_code;

比将它们全部用于更改并在出现更改时引发错误。 有没有其他更好的方法来做到这一点。 因为它采用了500种不同的变量声明和更多的比较。请帮助我这方面

简单地说:在我的表格中,如果用户尝试更改任何其他内容,则应该只能更改一个特定列,这会引发错误。

1 个答案:

答案 0 :(得分:3)

这对触发器中可用的COLUMNS_UPDATED()函数很有用。

如果只更新了第四列,那么它返回的位模式将类似于

00001000 00000000 00000000 00000000 ... (binary)

即。第一个字节的值为8,其余为零,如果更新了任何其他列,则第一个字节将不等于8,或者其他一个不会为0.

该函数返回一个varbinary,每列一位。对于250列,它将返回32字节的数据(250/8),这意味着您将需要测试每个字节,即。

IF (    (SUBSTRING(COLUMNS_UPDATED(), 1,1) = 8) 
    AND (SUBSTRING(COLUMNS_UPDATED(), 2,1) = 0) 
    AND (SUBSTRING(COLUMNS_UPDATED(), 3,1) = 0) 
    .
    .
    .
    AND (SUBSTRING(COLUMNS_UPDATED(),31,1) = 0) 
    AND (SUBSTRING(COLUMNS_UPDATED(),32,1) = 0) 
) 

这测试了一个特定的列已经更新。如果您有多个可以更新的列,那么您将需要一些按位运算符来过滤位模式。