1

第一次在这里发帖。

我想创建一个触发器,以便当有人尝试更新表时,它会阻止更新并将尝试记录在审计表中。

USE [AdventureWorks2008R2]
GO

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [Person].[Lastname_Trigger]
ON [Person].[Person]
FOR UPDATE AS
       IF UPDATE (Lastname)
       BEGIN 
          INSERT INTO SurnameChange (BusinessEntityID, Firstname, OldLastName, NewLastName,AttemptedBy, Timestamped)
             SELECT
                d.businessentityid,
                i.firstname,
                d.lastname,
                i.lastname,
                SUSER_SNAME(),
                GETDATE()
             FROM deleted d , inserted i
             WHERE d.businessentityid = i.businessentityid
       END 

       /*This is where it is going wrong*/
       BEGIN TRANSACTION
          IF UPDATE(lastname)
          BEGIN
              RAISERROR ('cannot change lastname', 16, 1)
              ROLLBACK TRANSACTION
              RETURN
          END 

如果有人可以帮助我,那就太好了,我已经使用 AdventureWorks 作为示例,因此它对其他人来说是通用的和可用的。

非常感谢。

詹姆士

4

1 回答 1

1

尝试这个:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [Person].[Lastname_Trigger]
ON [Person].[Person]
FOR UPDATE AS
       IF UPDATE (Lastname)
       BEGIN 
          INSERT INTO SurnameChange (BusinessEntityID, Firstname, OldLastName, NewLastName,AttemptedBy, Timestamped)
             SELECT
                d.businessentityid,
                i.firstname,
                d.lastname,
                i.lastname,
                SUSER_SNAME(),
                GETDATE()
             FROM deleted d
             INNER JOIN inserted i ON d.businessentityid = i.businessentityid

          RAISERROR ('cannot change lastname', 16, 1)
          ROLLBACK TRANSACTION
       END

       RETURN

我看不出有任何理由 (a)再次检查是否LastName已更新,并且 (b) 确实不需要在触发器内启动事务。

由于您想防止实际UPDATE发生 - 只是已经在进行ROLLBACK中的事务(对于命令)并完成它。UPDATE

旁注:请将您的 SQL 知识升级JOIN到“新”正确的 ANSI SQL语法(在 20 多年前与 SQL-92 标准一起引入) - 使用INNER JOINLEFT OUTER JOIN并停止使用逗号分隔的表列表

于 2013-05-16T21:13:03.297 回答