Sql server 2008 使用和更新触发器修改正在更新的行
我有一个employee表(em),其中包含楼层Id(fl_Id)和房间Id(rm_Id)。在某些情况下(当em_loc_cnt=0时),我希望将em记录的fl_id和rm_id设置为null。下面是到目前为止我的代码 我不知道如何在注释行中引用fl_id和rm_id。由于em记录被更新而调用此触发器,并且我正在更新触发器中的同一记录,我是否会遇到问题 建议Sql server 2008 使用和更新触发器修改正在更新的行,sql-server-2008,Sql Server 2008,我有一个employee表(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_ser
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;
您的基本缺陷是,您似乎希望触发器每行触发一次——SQL Server中的情况并非如此。相反,触发器对每条语句触发一次,插入的伪表
可能包含多行
鉴于该表可能包含多行,您希望在此处选择哪一行
SET @em_id = (SELECT em_id FROM 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)
对于SQL Server 2005和更新版本,我始终建议使用新的、重点突出的目录视图,如sys.triggers
,而不是使用旧的、不推荐使用的sysobjects
,并且必须指定要查找的对象的类型……请您将列命名得更模糊一些,意义更小一些,好吗?此外,如果更新影响多行,您的触发器将失效……并且em_loc_cnt=0?@AaronBertrand:现在好了吗?:-)我想是的。:-)这不是我将使用的语法(从em-internal-JOIN-inserted更新em
),但这是一个不同的故事。:-)