7

问:
在我们的 SQL-Server 2005 数据库中,我们有一个表 T_Groups。
T_Groups 具有字段 ID (PK) 和名称等。

现在我们公司的一些白痴使用名称作为映射表中的键......
这意味着现在人们可能不会更改组名,因为如果这样做,映射就消失了......
现在,直到解决这个问题,我需要为 T_Groups 添加限制,因此无法更新组的名称。
请注意,插入应该仍然是可能的,并且不更改组名的更新也应该是可能的。

另请注意,应用程序的用户和开发人员同时拥有 dbo 和 sysadmin 权限,因此 REVOKE/DENY 不起作用。

我怎样才能用触发器做到这一点?

4

4 回答 4

15
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
于 2012-10-26T07:41:39.560 回答
8
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 的答案。一些框架会生成包含所有列的 SQL 更新语句,即使它们没有更改,例如

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

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

于 2012-10-26T07:33:07.453 回答
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
于 2021-04-08T06:06:01.497 回答
0

此示例将通过触发器锁定 SABENTIS_LOCATION.fk_sabentis_location 上的任何更新,并将输出一条详细消息,指示哪些对象受到影响

ALTER TRIGGER dbo.SABENTIS_LOCATION_update_fk_sabentis_location ON SABENTIS_LOCATION
FOR UPDATE
AS
DECLARE @affected nvarchar(max)
SELECT @affected=STRING_AGG(convert(nvarchar(50), a.id), ', ')
  FROM inserted a
  JOIN deleted b ON a.id = b.id
  WHERE a.fk_sabentis_location != b.fk_sabentis_location
IF @affected != ''
BEGIN
  ROLLBACK TRAN
  DECLARE @message nvarchar(max) = CONCAT('Update values on column fk_sabentis_location locked by custom trigger. Could not update entities: ', @affected);
  RAISERROR(@message, 16, 1)
END

一些示例似乎正在使用:

IF UPDATE(name)

但是,如果该字段是更新语句的一部分,这似乎评估为 TRUE,即使该值本身没有更改导致误报。

于 2021-10-28T07:51:20.543 回答