2014-02-10 112 views
1

我有一個僱員表(em),其中包含樓層標識(fl_id)和房間標識(rm_id)等。在某些情況下(當em_loc_cnt = 0時),我想將em記錄的fl_id和rm_id設置爲null。以下是我的代碼到目前爲止。使用和UPDATE觸發器修改正在更新的行

我不確定如何在註釋行中引用fl_id & rm_id。我會碰到問題,因爲這個觸發器正在被更新的EM記錄的結果被調用,我正在更新觸發器中的相同記錄?

對此提出建議?

IF EXISTS (SELECT * FROM [sysobjects] WHERE [name] = 'em_upd_self_serv_t' AND [type] = 'TR') 
    BEGIN 
    DROP TRIGGER [dbo].[em_upd_self_serv_t] 
END 
GO 

CREATE TRIGGER [dbo].[em_upd_self_serv_t] 
    ON [dbo].[em] 
    AFTER UPDATE 
AS 
BEGIN 
    DECLARE @em_id VARCHAR(35), 
      @em_loc_cnt INT; 

    SET @em_id = (SELECT em_id FROM inserted); 
    SET @em_loc_cnt = (SELECT COUNT(*) FROM emlocs WHERE em_id = @em_id); 

    IF (@em_loc_cnt = 0) 
    BEGIN 
     -- I want to set the fl_id and the rm_id to NULL 
    END 
END; 
+0

對於SQL Server 2005 ** **和更新,我總是建議使用新的,重點目錄視圖像'sys.triggers'而不是使用舊的,不推薦使用的'sysobjects',並且必須指定要查找的對象的類型.... –

+0

請問您可以將您的列的名稱稍微模糊一點,但意義不大?此外,如果更新影響多於一行,觸發器將會崩潰。 –

回答

2

你根本缺陷是,你似乎期望觸發被解僱行一次 - 這是在SQL Server的情況。相反,觸發器會根據語句觸發一次,而僞表Inserted可能包含多行

鑑於該表可能包含多行 - 您期望在此處選擇哪一個?

SET @em_id = (SELECT em_id FROM inserted); 

它未定義 - 您可能會從Inserted中的任意行獲取值。

您需要用知識重寫您的整個觸發器Inserted包含多行!您需要使用基於集合的操作 - 不要指望Inserted中只有一行!

您需要更改您的代碼是這樣的:

IF EXISTS (SELECT * FROM sys.triggers WHERE [name] = 'em_upd_self_serv_t') 
    DROP TRIGGER [dbo].[em_upd_self_serv_t] 
GO 

CREATE TRIGGER [dbo].[em_upd_self_serv_t] 
    ON [dbo].[em] 
    AFTER UPDATE 
AS 
    UPDATE dbo.em 
    SET fl_id = NULL, rm_id = NULL 
    FROM Inserted i 
    WHERE em_id = i.em_id 
    AND NOT EXISTS (SELECT * FROM dbo.emlocs WHERE em_id = i.em_id) 
+0

... AND em_loc_cnt = 0? –

+0

@AaronBertrand:現在好多了? :-) –

+1

我這麼認爲。 :-)這不是我將使用的語法('UPDATE em FROM em INNER JOIN inserted'),但這是一個不同的故事。 :-) –