2010-01-05 117 views
9

我寫了一個觸發器,需要根據實際更新的行中的哪些列對錶執行一些不同的工作。我用TSql觸發器只需要觸發其值已更改的列

IF UPDATE(column-name) 

這部分工作正常。然而,事實證明,代碼的其他部分通過設置每個值來更新行,而不管該值是否實際發生了更改,這會導致觸發器針對「已更新」但其值未實際發生更改的部分觸發在所有。

由於改變導致這種情況的代碼可能不是一種選擇,是否有一種更簡單的方法來防止這種情況,而不是必須在INSERTED和DELETED表之間進行比較(在這種情況下,IF UPDATE是無意義的)?

回答

14
IF EXISTS (SELECT * 
      FROM 
      INSERTED I JOIN DELETED D ON I.Key = D.Key 
      WHERE 
      I.Col <> D.Col) 
... 

,或者使用一個表變量從而緩存避免重複使用的我和D

SELECT 
    CASE WHEN I.Col1 <> D.Col1 THEN 1 ELSE 0 END AS Col1Diff, 
    CASE WHEN I.Col2 <> D.Col2 THEN 1 ELSE 0 END AS Col2Diff, 
    ... 
FROM 
    INSERTED I JOIN DELETED D ON I.Key = D.Key 

或合併的想法,以測試所有更改前面和退出觸發

2

不是我所知道的。 INSERTEDDELETED是有原因的,他們之間的比較似乎是我的最佳選擇。

IF UPDATE()只是告訴你,如果插入或更新嘗試已作出,並且甚至不反映該嘗試是否成功。

4

該列已更新。舊的價值和新的價值是一樣的只是一個細節。我認爲你唯一的解決方案是比較插入和刪除僞表之間的值。

7

正如其他人所說,你必須使用INSERTEDDELETED表。

這裏是我做了什麼,而不是:

IF UPDATE(col1) OR UPDATE(col2)) 
UPDATE table1 
SET col3 = 1 
FROM INSERTED 
WHERE table1.Id = INSERTED.Id 

我做:

IF UPDATE(col1) OR UPDATE(col2)) 
UPDATE table1 
SET col3 = 1 
FROM 
    (SELECT Id, col1, col2 FROM INSERTED 
    EXCEPT 
    SELECT Id, col1, col2 FROM DELETED) AS ALTERED 
WHERE table1.Id = ALTERED.Id 

使用EXCEPT選擇其中列我感興趣的刪除不存在重複行(或原始數據)表(表示這些列的值已更改)。我不知道這是否是最好的答案,但似乎確實起作用。