Sql 如何有效地防止对触发器中除一列以外的所有列进行更新?

Sql 如何有效地防止对触发器中除一列以外的所有列进行更新?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个250列的表,我必须在上面写一个触发器,它将阻止除一列之外的所有列的更新 有一个列evt_updateable,它是可更新的。触发器的职责是在用户尝试更新除此列以外的任何内容时引发错误 实现这一目标的不同方式有哪些。 一种方法是声明500个变量,这些变量存储插入和删除的值。如下面的代码片段所示 SELECT @newColdata1 = i.col1 @oldColdata1 = d.col

我有一个250列的表,我必须在上面写一个触发器,它将阻止除一列之外的所有列的更新

有一个列evt_updateable,它是可更新的。触发器的职责是在用户尝试更新除此列以外的任何内容时引发错误

实现这一目标的不同方式有哪些。 一种方法是声明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个不同的变量声明和更多的比较。请在这方面帮助我


简单地说:在我的表中,如果用户试图更改任何内容,则只能更改一个特定的列。触发器将引发错误。

这是触发器中可用函数的一个很好的用途

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

00001000 00000000 00000000 00000000 ... (binary)
i、 e.第一个字节的值为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) 
) 

这将测试是否只更新了一个特定列。如果有多个可以更新的列,则需要一些按位运算符来过滤位模式。

用户如何更新数据?您是否提供了一些用户界面?如果是,那么为什么不将它们限制在那里,而不是将此操作一直委托给触发器。@Pawan将此业务逻辑放在数据库层中,可以使数据库向开发人员开放,并使他们每个人都不必重新实现业务规则。这遵循了干燥的原则(不要重复你自己),是一个很好的实践。你为什么不使用权限呢?您可以授予指定列的更新权限,并拒绝对其余列的更新。@johan我不能这样做,因为我对数据库没有DBA权限