仅当修改列时才触发SQL更新

仅当修改列时才触发SQL更新,sql,sql-server,triggers,Sql,Sql Server,Triggers,通过查看其他示例,我得出了以下结论,但它似乎没有像我所希望的那样工作:我希望它仅在QtyToRepair值已更新时更新修改过的信息。。。但它不能做到这一点 如果我注释掉where,那么在任何情况下修改的信息都会更新。正如我所说的,其他例子让我变得乐观。任何线索都很感激。谢谢 沃尔特 ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] ON [dbo].[SCHEDULE] AFTER UPDATE AS BEGIN SET NOCOUNT

通过查看其他示例,我得出了以下结论,但它似乎没有像我所希望的那样工作:我希望它仅在
QtyToRepair
值已更新时更新修改过的信息。。。但它不能做到这一点

如果我注释掉where,那么在任何情况下修改的信息都会更新。正如我所说的,其他例子让我变得乐观。任何线索都很感激。谢谢

沃尔特

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    UPDATE SCHEDULE SET modified = GETDATE()
        , ModifiedUser = SUSER_NAME()
        , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S
    INNER JOIN Inserted I on S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    WHERE S.QtyToRepair <> I.QtyToRepair
END
ALTER TRIGGER[dbo]。[tr\u SCHEDULE\u Modified]
在[dbo].[附表]
更新后
作为
开始
不计数;
更新计划集已修改=GETDATE()
,ModifiedUser=SUSER_NAME()
,ModifiedHost=主机名()
附表S
在S.OrderNo=I.OrderNo和S.PartNumber=I.PartNumber上插入的内部联接I
其中S.QtyToRepair I.QtyToRepair
结束

您要执行以下操作:

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;

    IF (UPDATE(QtyToRepair))
    BEGIN
        UPDATE SCHEDULE SET modified = GETDATE()
            , ModifiedUser = SUSER_NAME()
            , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo AND S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END
ALTER TRIGGER[dbo]。[tr\u SCHEDULE\u Modified]
在[dbo].[附表]
更新后
作为
开始
不计数;
如果(更新(修复))
开始
更新计划集已修改=GETDATE()
,ModifiedUser=SUSER_NAME()
,ModifiedHost=主机名()
附表S
在S.OrderNo=I.OrderNo和S.PartNumber=I.PartNumber上插入的内部联接I
其中S.QtyToRepair I.QtyToRepair
结束
结束

请注意,无论值是否相同,每次更新列时都会触发此触发器。

首先应检查是否更新了
QtyToRepair

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
            ON S.OrderNo = I.OrderNo and S.PartNumber =    I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END
ALTER TRIGGER[dbo]。[tr\u SCHEDULE\u Modified]
在[dbo].[附表]
更新后
作为
开始
不计数;
如果更新(QtyToRepair)
开始
更新时间表
SET modified=GETDATE()
,ModifiedUser=SUSER_NAME()
,ModifiedHost=主机名()
从插入的明细表S内部联接I
在S.OrderNo=I.OrderNo和S.PartNumber=I.PartNumber上
其中S.QtyToRepair I.QtyToRepair
结束
结束

你的问题有两种方式:

1-在触发器中使用Update命令

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
        ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END 
END
ALTER TRIGGER[dbo]。[tr\u SCHEDULE\u Modified]
在[dbo].[附表]
更新后
作为开始
不计数;
如果更新(QtyToRepair)
开始
更新时间表
SET modified=GETDATE()
,ModifiedUser=SUSER_NAME()
,ModifiedHost=主机名()
从插入的明细表S内部联接I
在S.OrderNo=I.OrderNo和S.PartNumber=I.PartNumber上
其中S.QtyToRepair I.QtyToRepair
结束
结束
2-在插入表和删除表之间使用联接

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;    

    UPDATE SCHEDULE 
    SET modified = GETDATE()
       , ModifiedUser = SUSER_NAME()
       , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S 
    INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber                  
    WHERE S.QtyToRepair <> I.QtyToRepair
    AND D.QtyToRepair <> I.QtyToRepair
END
ALTER TRIGGER[dbo]。[tr\u SCHEDULE\u Modified]
在[dbo].[附表]
更新后
作为开始
不计数;
更新时间表
SET modified=GETDATE()
,ModifiedUser=SUSER_NAME()
,ModifiedHost=主机名()
附表S
在S.OrderNo=I.OrderNo和S.PartNumber=I.PartNumber上插入的内部联接I
在S.OrderNo=D.OrderNo和S.PartNumber=D.PartNumber上删除了D的内部联接
其中S.QtyToRepair I.QtyToRepair
和D.QtyToRepair I.QtyToRepair
结束

当您对表
SCHEDULE
使用update命令并将
QtyToRepair
列设置为新值时,如果一行或多行中的新值等于旧值,则解决方案1将更新计划表中所有更新的行,但解决方案2仅更新旧值不等于新值的计划行。

仅供参考,代码I最终为:

IF UPDATE (QtyToRepair)
    begin
        INSERT INTO tmpQtyToRepairChanges (OrderNo, PartNumber, ModifiedDate, ModifiedUser, ModifiedHost, QtyToRepairOld, QtyToRepairNew)
        SELECT S.OrderNo, S.PartNumber, GETDATE(), SUSER_NAME(), HOST_NAME(), D.QtyToRepair, I.QtyToRepair FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber 
        WHERE I.QtyToRepair <> D.QtyToRepair
end
IF更新(QtyToRepair)
开始
插入tmpQtyToRepairChanges(订单号、零件号、ModifiedDate、ModifiedUser、ModifiedHost、QtyToRepairOld、QtyToRepairNew)
从计划S中选择S.OrderNo、S.PartNumber、GETDATE()、SUSER_NAME()、HOST_NAME()、D.QtyToRepair、I.QtyToRepair
在S.OrderNo=I.OrderNo和S.PartNumber=I.PartNumber上插入的内部联接I
在S.OrderNo=D.OrderNo和S.PartNumber=D.PartNumber上删除了D的内部联接
其中I.QtyToRepair D.QtyToRepair
结束

每当记录更新时,记录都会被“删除”。以下是我的例子:

ALTER TRIGGER [dbo].[UpdatePhyDate]
   ON  [dbo].[M_ContractDT1]
   AFTER UPDATE
AS 
BEGIN
    -- on ContarctDT1 PhyQty is updated 
    -- I want system date in Phytate automatically saved
    SET NOCOUNT ON;

    declare @dt1ky as int   

    if(update(Phyqty))
    begin
        select @dt1ky = dt1ky from deleted

        update M_ContractDT1 set PhyDate=GETDATE() where Dt1Ky=  @dt1ky     

    end

END


它工作正常

关于
update()
的警告-它只测试列是否出现在更新列表中,对于插入总是正确的。它不会检查列值是否已更改,因为您可能有多行,其中一些值已更改,而一些值未更改。很抱歉,没有提及它是SQLServer。我需要使用已删除的表。我最后写入了一个单独的表(以维护历史记录)。如果您不希望在列被更改为相同值时触发触发器,那么方法#2会更好。我想我可能遗漏了一些东西,但方法#1不起作用,因为这是在更新之后,所以当前行始终具有与插入行相同的值。如果在之后使用,则必须加入以删除update@Rob“IF UPDATE”语句正在调用一个过程,该过程可以访问作为查询一部分更新的列列表,因此不需要知道以前的值。(我们刚刚在我们的环境中遇到了这个问题,并确认不管“AFTER UPDATE”子句如何,都会遵守“IF UPDATE”命令)为什么要在第二个查询中加入
inserted
表?它应该和桌子本身一样,不是吗?我发现这很有帮助,因为上面答案之间的2-Use连接从未起作用,因为where条件
where S.QtyToRepair I.QtyToRepair和D.QtyToRepair I.QtyToRepair
从未触发/匹配,因为第一个条件从未为真-插入的表始终与实际表值匹配。使用'WHERE I.QtyToRepair D.QtyToRepair'是我的关键。还有来自多个触发器的
IF更新(字段)
帮助。