2014-09-22 125 views
0

我必須在UPDATE或DELETE操作中觸發一個觸發器。當某個列更新時,我的觸發器工作正常。但是,我需要不同的邏輯來處理DELETE操作。我如何在一個觸發器中同時具有邏輯?這是我到目前爲止有:通過觀察其magic- /僞表的更新或刪除SQL觸發器

ALTER TRIGGER [dbo].[Audit_Emp_Trigger] 
    ON [dbo].[EMPLOYEE] 
    AFTER UPDATE, DELETE 
AS 

BEGIN 
    --Only execute the trigger if the Dno field was updated or deleted 
    IF UPDATE(Dno) 
    BEGIN 

    --If the Audit_Emp_Record table does not exist already, we need to create it 
    IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL 
    BEGIN 
    --Table does not exist in database, so create table 
    CREATE TABLE Audit_Emp_Record 
    (
    date_of_change smalldatetime, 
    old_Lname varchar (50), 
    new_Lname varchar (50), 
    old_ssn int, 
    new_ssn int, 
    old_dno int, 
    new_dno int 
    ); 

    --Once table is created, insert the values of the update operation into the table 
    INSERT INTO Audit_Emp_Record(date_of_change, old_Lname, new_Lname, old_ssn, new_ssn, old_dno, new_dno) SELECT GETDATE(), D.Lname, I.Lname, D.Ssn, I.Ssn, D.Dno, I.Dno FROM inserted I JOIN deleted D ON I.Ssn = D.Ssn 

    END 

    ELSE 
    BEGIN 
    --The table already exists, so simply insert the new values of the update operation into the table 
    INSERT INTO Audit_Emp_Record(date_of_change, old_Lname, new_Lname, old_ssn, new_ssn, old_dno, new_dno) SELECT GETDATE(), D.Lname, I.Lname, D.Ssn, I.Ssn, D.Dno, I.Dno FROM inserted I JOIN deleted D ON I.Ssn = D.Ssn 
    END 

    END 

END 
+0

如果邏輯是'UPDATE'和'DELETE'之間如此不同 - 爲什麼不只是有兩個獨立的觸發器,每個專注於自己的一個操作? – 2014-09-22 04:27:08

+0

@marc_s:與我的回答相關的評論顯示,邏輯並沒有完全不同。兩個操作都將數據記錄到同一個審計表; 'UPDATE'加入'INSERTED'和DELETED'表,'DELETE'只是從DELETED表中拉出。只是FYI。 – 2014-09-22 20:02:43

回答

2

可以測試操作的類型 - INSERTEDDELETED在他們的數據。我更喜歡使用類似以下內容:

DECLARE @Operation CHAR(1); 

IF (EXISTS(SELECT * FROM inserted)) 
BEGIN 

    IF (EXISTS(SELECT * FROM deleted)) 
    BEGIN 
     -- rows in both has to be an UPDATE 
     SET @Operation = 'U'; 
    END; 
    ELSE 
    BEGIN 
     -- no rows in "deleted" has to be an INSERT 
     SET @Operation = 'I'; 
    END; 

END; 
ELSE 
BEGIN 
    -- no rows in "inserted" has to be a DELETE 
    SET @Operation = 'D'; 
END; 

然後,您可以使用@Operation變量IF語句做一個或其他的操作。

喜歡的東西:

IF (@Operation = 'U') 
BEGIN 

    --Only execute the trigger if the Dno field was updated or deleted 
    IF UPDATE(Dno) 
    BEGIN 
     {your current code here} 
    END; 
END; 
ELSE 
BEGIN 
    {what to do if the operation is a DELETE goes here} 
END; 

從技術上講,你不需要ELSE條件,設置@Operation = 'I';,但如果你要複製/將此代碼粘貼到各個觸發器或保持周圍作爲模板的話沒有惡意在它處理所有三個條件。

而且,就像一個側面說明,你不需要ELSE條件IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL聲明,也不INSERT INTO Audit_Emp_Record剛好在CREATE TABLE之後,但在END之前。只要執行CREATE TABLE(如果不存在),然後在該測試之外執行INSERT即可。含義:

IF UPDATE(Dno) 
BEGIN 
    --If the Audit_Emp_Record table does not exist already, we need to create it 
    IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL 
    BEGIN 
     --Table does not exist in database, so create table 
     CREATE TABLE Audit_Emp_Record 
     ... 
    END 

    INSERT INTO Audit_Emp_Record(...) 
END 
+0

我無法做一個ELSE,因爲我只想執行IF UPDATE(Dno)中的代碼塊,如果Dno列被更新,而不是任何其他列 – 2014-09-22 01:44:44

+0

@JonathanDurda:啊,好點。我想我可以刪除我的答案那部分。這只是我腦海中浮現的東西。但第一部分仍然存在。 – 2014-09-22 01:49:53

+0

謝謝你的解決方案。我唯一的問題是,我能夠通過掃描已刪除的表來判斷哪一列已被刪除?例如,如果Dno列被刪除,我只想在DELETE塊內部執行代碼。 – 2014-09-22 01:58:31