2013-05-16 84 views
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爲例如所以它是通用的,可用於其他。

非常感謝。

詹姆斯

+1

['INSTEAD OF'觸發器](http://msdn.microsoft.com/en-us/library/ms179288(v = sql.105).aspx)可能更容易這裏;顧名思義,無論你放在觸發器中運行的是什麼,而不是觸發操作,所以最初的'INSERT'根本不會被執行。 – Pondlife

回答

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 

我看不出有任何理由(一)檢查再次如果LastName已經更新,和(b)真的沒有必要啓動觸發器內的事務。

既然要防止實際UPDATE的發生 - 只是ROLLBACK這已經正在進行(用於UPDATE命令),並用它做交易。

邊注:請升級您的SQL知識以「新」適當的ANSI SQL語法JOIN(介紹20多年前與SQL-92標準) - 使用INNER JOINLEFT OUTER JOIN等,並停止使用逗號分隔的列表

+0

謝謝!我知道這會很簡單。 – Jay

+1

沒問題。仍然習慣了網站,所以感謝您指出它應該我再次發佈。 – Jay