我有一个员工表(em),其中包含楼层ID(fl_id)和房间ID(rm_id)。在某些情况下(当em_loc_cnt = 0时)我想将em记录的fl_id和rm_id设置为null。以下是我目前的代码。
我不确定如何引用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 :(得分:2)
您的根本缺陷是,您似乎希望触发器每行一次 - 这在SQL Server中是 NOT 。相反,触发器会在每个语句时触发,而伪表Inserted
可能包含多行。
鉴于该表可能包含多行 - 您希望在这里选择哪一行?
SET @em_id = (SELECT em_id FROM inserted);
未定义 - 您可以从Inserted
中的任意行获取值。
您需要使用Inserted
WILL 包含多行的知识重写整个触发器!您需要使用基于集合的操作 - 不要只期望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)