未更新时,SQL触发器触发列更新

时间:2017-06-29 12:04:17

标签: sql-server tsql

我认为我的问题出在以下几行......

IF NOT UPDATE(DateCompleted)或NOT EXISTS(在DateCompleted为null时选择DateCompleted FROM DELETED) RETURN

我想要实现的是,如果DateCompleted已经更新了以前没有的日期,那么触发器只会触发。

我刚刚运行了一个测试,其中Job已更新且DateCompleted尚未设置(仍为NULL)但触发器已触发

史蒂夫

        CREATE TRIGGER [dbo].[trgJobCompletion] 
       ON  [dbo].[Job] 
       AFTER UPDATE
    AS 

    -- Make sure DateCompleted was changed and was previously NULL
    IF NOT UPDATE(DateCompleted) or NOT EXISTS(SELECT DateCompleted FROM DELETED where DateCompleted is null)
        RETURN

    -- Only interested in Maintenance, Contract Repair or Repair Jobs
    DECLARE @JobTypeID as int;
    select @JobTypeID = inserted.LookUpJobTypeID from inserted;
    IF NOT @JobTypeID = 9 AND NOT @JobTypeID = 2  AND NOT @JobTypeID = 1
        RETURN 

    DECLARE @JobID as int;
    DECLARE @ContractNumber as int;
    DECLARE @SiteID as int;
    select @JobID = inserted.ID from inserted;
    select @ContractNumber = Contract.ContractNumber from inserted left join Site on Site.ID = inserted.SiteID left join Contract on Contract.ID = Site.ContractID;
    select @SiteID = inserted.SiteID from inserted;

    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;

        -- Insert statements for trigger here

        insert into JobCompletedLog(JobID,LookUpJobTypeID,ContractNumber,SiteID,LogCreated) 
        values(@JobID,@JobTypeID,@ContractNumber,@SiteID,getdate());


    END

2 个答案:

答案 0 :(得分:1)

你的触发器有一个根本的缺陷,这是在内存驻留表inserted只包含一行的前提下工作的,例如

select @JobID = inserted.ID from inserted;

inserted可以包含多行,您实际上是从该表中随机分配一个值到标量变量@JobID

如果任何行已更新,同样UPDATE(DateCompleted)将返回true,因此您仍然可以为尚未完成的作业插入记录。

即使您认为由于其他进程一次只更新一行,您应该始终编写触发器以处理多行。没有例外。

你的触发器应该是

CREATE TRIGGER [dbo].[trgJobCompletion] 
ON  [dbo].[Job] 
AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT JobCompletedLog(JobID,LookUpJobTypeID,ContractNumber,SiteID,LogCreated) 
    SELECT  i.ID, i.LookUpJobTypeID, c.ContractNumber, i.siteID, GETDATE()
    FROM    inserted AS i
            INNER JOIN deleted AS d
                ON d.ID = i.ID
            LEFT JOIN Site AS s
                ON s.ID = i.SiteID
            LEFT JOIN Contract AS c
                ON c.ID = s.ContractID
    WHERE   i.LookUpJobTypeID IN (9, 2, 1)  -- Only interested in Maintenance, Contract Repair or Repair Jobs
    AND     i.DateCompleted IS NOT NULL     -- Date Completed has been set
    AND     d.DateCompleted IS NULL         -- Date Completed was previously null

END

答案 1 :(得分:0)

我认为DateCompleted列可以为空,并且您希望在DateCompleted列更改或删除DateCompleted时触发触发器。如果是这样,您应该更改不存在的子查询。尝试下面的你自己的行。

IF NOT UPDATE(DateCompleted)或NOT EXISTS(SELECT * FROM DELETED,其中DateCompleted为null)