SQL SERVER TRIGGER使用更新的值

时间:2013-12-03 13:37:39

标签: sql-server triggers

我在触发TICKETS表中所有状态更改的日期时使用触发器: 我确实在上面尝试过它,但它正在响应:“无效的对象名称'UPDATED'”。

CREATE TRIGGER TG_TICKETS_STATUS_HISTORY
ON TICKETS_TI AFTER UPDATE 
AS 
BEGIN

    DECLARE @ID INT
    DECLARE @STATUS INT

    SELECT @ID = ID, 
        @STATUS = STATUS
    FROM UPDATED 


    IF (@STATUS != (
        SELECT TOP 1 SH.STS_NAME
        FROM TICKETS_STATUS_HISTORY SH
        WHERE SH.ID = @ID
        ORDER BY SH.STS_DATE DESC
    ))
    BEGIN
        INSERT INTO TICKETS_STATUS_HISTORY
        VALUES (@ID, @STATUS, GETDATE())
    END
END

2 个答案:

答案 0 :(得分:2)

你应该拥有的是:

CREATE TRIGGER TG_TICKETS_STATUS_HISTORY
ON TICKETS_TI AFTER UPDATE 
AS 
BEGIN

INSERT INTO TICKETS_STATUS_HISTORY (ID,STS_NAME,STS_DATE)
select i.ID,i.Status,GETDATE()
from inserted i
    inner join (
     select ID,STS_NAME,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY STS_DATE desc) as rn
     from TICKETS_STATUS_HISTORY
    ) h
      on
         i.ID = h.ID and
         i.STATUS != h.STS_NAME and
         h.rn = 1

END

inserted(和deleted)是一个pseudo-table,可以包含0,1或多个行。将列值分配给标量变量(例如

SELECT @ID = ID, 
    @STATUS = STATUS
FROM INSERTED 

)是完全错误的。


如果您只想检查状态列值是否已更改(并且不需要在历史记录表中查找),我们可以使其更简单:

INSERT INTO TICKETS_STATUS_HISTORY (ID,STS_NAME,STS_DATE)
select i.ID,i.Status,GETDATE()
from inserted i
    inner join
     deleted d
      on
         i.ID = d.ID and
         i.STATUS != d.STATUS

答案 1 :(得分:1)

您应该使用INSERTED表而不是UPDATED,因为更新操作包括删除操作和插入操作。

DELETED表中,您会找到旧的值,在INSERTED中,您会找到新的(已更新的)值。

此外,在触发器声明中,您应该使用FOR关键字而不是ON来引用应该启动触发器的操作。

例如

CREATE TRIGGER TG_TICKETS_STATUS_HISTORY
ON TICKETS_TI 
FOR UPDATE 
AS 
BEGIN    
    INSERT INTO TICKETS_STATUS_HISTORY
    SELECT I.ID, I.STATUS, GETDATE()
    FROM INSERTED I
    INNER JOIN DELETED D 
       ON I.ID = D.ID 
       AND I.STATUS != L.STATUS
END