T-SQL:如何通过触发器拒绝对表的一列进行更新?

时间:2012-10-26 07:25:07

标签: sql sql-server tsql sql-server-2005 sql-server-2008-r2

问题:
在我们的SQL-Server 2005数据库中,我们有一个表T_Groups 除其他外,T_Groups还包括字段ID(PK)和名称。

现在我们公司的一些白痴使用这个名字作为映射表的关键...
这意味着现在可能不会改变组名,因为如果有的话,映射就会消失......
现在,在解决此问题之前,我需要为T_Groups添加限制,因此无法更新组的名称。
请注意,插入仍然是可能的,并且还应该可以进行不更改组名的更新。

另请注意应用程序的用户&开发人员拥有dbo和sysadmin权限,因此REVOKE / DENY将无法正常工作。

如何使用触发器执行此操作?

3 个答案:

答案 0 :(得分:11)

CREATE TRIGGER dbo.yournametrigger ON T_Groups
FOR UPDATE
AS
BEGIN
  IF UPDATE(name)
  BEGIN
    ROLLBACK
    RAISERROR('Changes column name not allowed', 16, 1);
  END
  ELSE
  BEGIN
  --possible update that doesn't change the groupname
  END
END

答案 1 :(得分:7)

CREATE TRIGGER tg_name_me
ON tbl_name
INSTEAD OF UPDATE
AS
IF EXISTS (
   SELECT *
   FROM INSERTED I
   JOIN DELETED D ON D.PK = I.PK AND ISNULL(D.name,I.name+'.') <> ISNULL(I.name,D.name+'.')
)
RAISERROR('Changes to the name in table tbl_name are NOT allowed', 16,1);
GO

根据您访问数据库的应用程序框架,检查更改的更便宜方法是Alexander's answer。某些框架将生成包含所有列的SQL更新语句,即使它们没有更改,例如

UPDATE TBL
   SET name = 'abc', -- unchanged
       col2 = null, -- changed
       ... etc all columns

UPDATE()函数仅检查语句中列是 present ,而不是其值是否已更改。此特定语句将使用UPDATE()引发错误,但如果使用如上所示的更复杂的触发器进行测试则不会。

答案 2 :(得分:0)

这是一个使用更新触发器保留一些原始值的示例。 它的工作原理是每次将 orig_author 和 orig_date 的值设置为已删除伪表中的值。它仍然执行工作并使用循环。

CREATE TRIGGER [dbo].[tru_my_table]  ON [dbo].[be_my_table]
AFTER UPDATE
AS
    UPDATE [dbo].[be_my_table]
    SET
    orig_author = deleted.orig_author
    orig_date   = deleted.orig_date,
    last_mod_by = SUSER_SNAME(),
    last_mod_dt = getdate()
    from deleted
    WHERE deleted.my_table_id IN  (SELECT DISTINCT my_table_id FROM Inserted)

ALTER TABLE [dbo].[be_my_table] ENABLE TRIGGER [tru_my_table]
GO