能否在SQL Server触发器中多次使用UPDATE()函数?

能否在SQL Server触发器中多次使用UPDATE()函数?,sql,sql-server,triggers,Sql,Sql Server,Triggers,我正在尝试测试触发器中更新了哪些列。我知道可以像这样使用更新功能 IF (UPDATE(Column1) OR UPDATE(Column2) OR UPDATE(Column3)) Do something... 但是我需要能够分别测试每一列,并且在以下方面没有取得任何成功 DECLARE TriggerCursor CURSOR READ_ONLY FOR SELECT SOPNUMBE, SOPTYPE, CMPNTSEQ, LNITMSEQ, ITE

我正在尝试测试触发器中更新了哪些列。我知道可以像这样使用更新功能

IF (UPDATE(Column1) OR UPDATE(Column2) OR UPDATE(Column3))
    Do something...
但是我需要能够分别测试每一列,并且在以下方面没有取得任何成功

DECLARE TriggerCursor CURSOR READ_ONLY FOR 
    SELECT 
        SOPNUMBE, SOPTYPE, CMPNTSEQ, LNITMSEQ, ITEMNMBR, 
        QUANTITY, UNITPRCE, PRSTADCD 
    FROM 
        inserted;

OPEN TriggerCursor;

FETCH NEXT FROM TriggerCursor INTO @sSOPNumber, @nSOPType, @nComponentSeq, 
                                   @nLineItemSeq, @sItemNumber, @cyQuantity, 
                                   @cyUnitPrice, @sShipToAddress;

WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)
    BEGIN
        IF UPDATE(QUANTITY)
        BEGIN
            SET @sAction = 'Changed Quantity from ' + RTRIM(CONVERT(CHAR,(select QUANTITY from deleted))) + ' to ' + RTRIM(CONVERT(CHAR, @cyQuantity));
        END;

        IF UPDATE(UNITPRCE)
        BEGIN
            IF LEN(@sAction) = ''
                SET @sAction = 'Changed Unit Price from ' + RTRIM(CONVERT(CHAR,(select UNITPRCE from deleted))) + ' to ' + RTRIM(CONVERT(CHAR, @cyUnitPrice));
            ELSE
                SET @sAction = @sAction + 'and Unit Price from ' + RTRIM(CONVERT(CHAR,(select UNITPRCE from deleted))) + ' to ' + RTRIM(CONVERT(CHAR, @cyUnitPrice));
            END;

            IF UPDATE(PRSTADCD)
            BEGIN
                IF @sAction = ''
                    SET @sAction = 'Changed ShipTo Address from ' + RTRIM(CONVERT(CHAR,(select PRSTADCD from deleted))) + ' to ' + RTRIM(CONVERT(CHAR, @sShipToAddress));
                ELSE
                    SET @sAction = @sAction + 'and ShipTo Address from ' + RTRIM(CONVERT(CHAR,(select PRSTADCD from deleted))) + ' to ' + RTRIM(CONVERT(CHAR, @sShipToAddress));
            END;

        EXEC NC_IDS_Insert_SOP_Audit_Record
                    @sSOPNumber, @nSOPType, @nComponentSeq,
                    @nLineItemSeq, @sUserId, @sAction, @dDate, @dTime;

    END;

    FETCH NEXT FROM TriggerCursor INTO  @sSOPNumber, @nSOPType, @nComponentSeq, @nLineItemSeq, @sItemNumber, @cyQuantity, @cyUnitPrice, @sShipToAddress;
END;

CLOSE TriggerCursor;
DEALLOCATE TriggerCursor;
每次似乎只测试第1列时,忽略其他列,即使在更新行时所有三列都已更新

编辑:忘记提到更新发生在光标内,所以不确定这是否是导致我的问题的原因?

当然可以。发件人:

返回一个布尔值,该值指示是否对表或视图的指定列进行了插入或更新尝试。UPDATE用于Transact-SQL插入或更新触发器主体内的任何位置,以测试触发器是否应执行某些操作

例如:

CREATE TABLE t(i INT, a INT, b INT, c INT);
INSERT INTO t(i,a,b,c) VALUES(1, 2,3,4);
INSERT INTO t(i,a,b,c) VALUES(2, 20,30,40);

CREATE TABLE log(t VARCHAR(MAX));

CREATE TRIGGER trg_t ON t AFTER UPDATE   
AS
BEGIN
   IF UPDATE(a)
   BEGIN
      INSERT INTO log VALUES ('Changed a');
   END;

   IF UPDATE(b)
   BEGIN
      INSERT INTO log VALUES ('Changed b');
   END;
END;

您需要记住,在SQL Server中,触发器是在语句级别激发的。

我更喜欢不涉及触发器的解决方案

从我的头顶上

SELECT PrimaryKeyColumn,SOPNUMBER, SOPTYPE, CMPNTSEQ, LNITMSEQ,  ITEMNMBR, QUANTITY, UNITPRCE, PRSTADCD 
INTO #mytemptable
FROM SomeTable
WHERE <matches the condition you want>

UPDATE SomeTable
SET SOPNUMBER=@newvalue, etc etc
WHERE <matches the condition you want>

INSERT INTO Audits (audit table columns)
SELECT T.SOPNUMBER,S.SOPNUMBER, etc, etc
FROM #mytemptable T
INNER JOIN SomeTable S
ON S.PrimaryKeyColumn=T.PrimaryKeyColumn

另外,尽量避免使用游标。通常可以使用基于集合的操作。

您需要提供一个mvce来演示您的问题。请注意。如果列是UPDATE语句的一部分,UPDATE函数将返回true。它不会评估新旧值是否不同。您的触发器已完全损坏。您有子查询从已删除数据中提取数据。你有一个常见的错误,那就是假设删除中只有一行。这在这一点上是一团糟。如果您想捕获数据更改,它应该是关系型的,而不是单个列中的文本解释。同样,更新不会检查不同的值,所以可以将单价从12.34更改为12.34。我更喜欢不涉及触发器的解决方案。获取与更新的where子句匹配的数据。很好的示例。从我对主要问题的评论中进一步阐述我的观点。如果执行Update t set a=a,b=b,则即使没有更改任何值,日志中也会有两个条目。我知道@lad2025知道这一点,所以会发表评论,让其他人理解这一点。@SeanLange我已经用我的触发器脚本进行了更新,因为我忘了提到它。更新发生在光标内