SQL Server触发器无法按预期工作

时间:2015-09-23 18:29:14

标签: sql-server triggers insert-update

我有3张桌子,小时,每日,记录

  • 小时有Id,StartDate,EndDate,EId,Hours
  • 每日有Id,日期
  • 记录有DailyId,EId,HourId

只要将新记录添加到Daily表中,就会在Record表中生成新行,其中包含预填充的DailyId和EId值。 HourId没有价值。因此,我希望有一个触发器,所以每次将新记录插入Hour表时,它都会更新HourId,其值来自Id of Hour表。显然,它必须匹配表中的EId和DailyId,另外,每日日期表必须在Hour表中新记录的StartDate和EndDate之间。

这是我的触发器,但每当我向Hour表添加新记录时它都不起作用。

ALTER TRIGGER [dbo].[insertRecord]
ON  [dbo].[Hour]
AFTER INSERT
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @EmpId nvarchar, @StartDate datetime, @EndDate datetime, 
            @EntId int, @ToHourId int

    SELECT @EmpId = EId FROM inserted
    SELECT @StartDate =  StartDate FROM inserted
    SELECT @EndDate = EndDate FROM inserted

    SELECT @EntId = a.Id, @ToHourId = c.HourId  
    FROM (Daily a 
    JOIN Record b ON a.Id = b.DailyId) 
    JOIN Hour c ON b.EId = c.EId
    WHERE b.EId = @EmpId AND a.Date BETWEEN @StartDate AND @EndDate

    -- Insert statements for trigger here

    UPDATE Record
    SET Record.HourId = @ToHourId
    FROM Record
    WHERE Record.EId = @EmpId 
        AND Record.DailyId = @EntId
        AND Record.HourId IS NULL 
END

1 个答案:

答案 0 :(得分:2)

您的根本缺陷是,您似乎希望触发器每行一次 - 这在SQL Server中是 NOT 。相反,触发器会在每个语句时触发,而伪表Inserted可能包含多行

鉴于该表可能包含多行 - 您希望在这里选择哪一行?

SELECT @EmpId = EId FROM inserted

未定义 - 您将从Inserted中的任意一行获取值,而忽略所有其他 - 通常您想要的内容。< / p>

您需要使用Inserted伪表 WILL 包含多行的知识重写整个触发器!您需要使用基于集合的操作 - 不要只期望Inserted中的一行!