2010-01-29 229 views
27

如果有:IF UPDATE()在SQL服務器觸發

IF UPDATE (col1) 

...在SQL服務器觸發器在表上只有COL1已經變更或更新,它返回true?

我有一個像

UPDATE table-name 
    SET col1 = 'x', 
     col2 = 'y' 
WHERE id = 999 

現在我關心的是什麼,如果所有「col1」是「X」以前那麼我們再次更新,以定期更新查詢「X」 會IF UPDATE ("col1")觸發器回真實與否?

我面臨這個問題,因爲我的保存查詢是所有列通用的,但是當我添加這個條件時,即使它沒有改變,它也會返回True ...所以我擔心在這種情況下如果我想要做什麼像這樣添加條件?

回答

39

如果列已更新,則返回true。更新意味着查詢已經設置了列的值。先前的價值與新價值是否相同在很大程度上是相關的。

UPDATE table SET col = col 

這是一個更新。

UPDATE table SET col = 99 

當col已經有值99也是更新。

+11

請注意,在INSERT上,對於ALL列,UPDATED()函數返回1。當然。 – ErikE 2012-07-27 23:57:34

+1

並刪除? – Rory 2015-03-24 17:12:53

+4

結果對於DELETE,UPDATE()函數不返回true。 http://stackoverflow.com/questions/29286034 – Rory 2015-03-26 18:22:52

10

在觸發器中,您可以訪問兩個可能有所幫助的內部表格。 '已插入'表格包含每個受影響行的新版本,'已刪除'表格包含每行的原始版本。您可以比較這些表中的值以查看您的字段值是否實際更改。

+0

其實,我想要這個檢查,以便執行不會更進一步,如果沒有更新 – 2010-01-29 21:27:32

+0

肯定 - 您使用帶有插入和刪除表的if語句來比較原始值和新值 - 如果字段已更改,做你的事情 - 如果沒有,請不要 – Ray 2010-01-29 22:44:53

2

你要做的是在插入和刪除表格中檢查不同的值,而不是使用updated()(不要忘記考慮空值)。或者你可以停止做不必要的更新。

1

到快捷「無實際更新」的情況下,你也需要檢查在開始查詢是否影響任何行的所有:

set nocount on; -- this must be the first statement! 
if not exists (select 1 from inserted) and not exists (select 1 from deleted) 
    return; 
2

這裏的掃描行的快捷方式,看看是否有列在決定運行觸發器的內容之前更改。例如,當你想寫一個歷史記錄時,這可能是有用的,但如果沒有真正改變,你不想這樣做。

我們一直在ETL導入過程中使用它,我們可以重新導入數據,但如果源文件中沒有真正改變,我們不想創建新的歷史記錄。

CREATE TRIGGER [dbo].[TR_my_table_create_history] 
ON [dbo].[my_table] FOR UPDATE AS 

BEGIN 

    -- 
    -- Insert the old data row if any column data changed 
    -- 
    INSERT INTO [my_table_history] 
    SELECT d.* 
    FROM deleted d 
    INNER JOIN inserted i ON i.[id] = d.[id] 
    -- 
    -- Use INTERSECT to see if anything REALLY changed 
    -- 
    WHERE NOT EXISTS(SELECT i.* INTERSECT SELECT d.*) 

END 

注意這個特殊的觸發假設你的源表(一個觸發扳機)和歷史表具有相同的列布局。

0
SET NOCOUNT ON; 

    declare @countTemp int 
    select @countTemp = Count (*) from (
    select City,PostCode,Street,CountryId,Address1 from Deleted 
    union 
    select City,PostCode,Street,CountryId,Address1 from Inserted 
    ) tempTable 

    IF (@countTemp > 1) 

Begin 

-- Your Code goes Here 
End 

-- if any of these "City,PostCode,Street,CountryId,Address1" got updated then trigger 

-- will work in " IF (@countTemp > 1) " Code) 
0
cREATE TRIGGER boo ON status2 FOR UPDATE AS 
IF UPDATE (id) 
BEGIN 
SELECT 'DETECT'; 
END; 

UPDATE status2 SET name = 'K' WHERE name= 'T' --no action 
UPDATE status2 SET name = 'T' ,id= 8 WHERE name= 'K' --detect 
0

這爲我工作

DECLARE @LongDescDirty bit = 0 

Declare @old varchar(4000) = (SELECT LongDescription from deleted) 
Declare @new varchar(4000) = (SELECT LongDescription from inserted) 

if (@old <> @new) 
    BEGIN 
     SET @LongDescDirty = 1 
    END 

Update table 
    Set LongDescUpdated = @LongDescUpdated 

.....

+2

這是不安全的,因爲插入和刪除可以包含多個記錄,如果UPDATE語句應用於多個記錄。 – PapillonUK 2016-09-10 15:01:37