Sql server 2008 使用和更新触发器修改正在更新的行

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

我有一个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_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
),但这是一个不同的故事。:-)