可以在SQL Server触发器中多次使用UPDATE()函数吗?

时间:2018-04-20 14:15:00

标签: sql sql-server triggers

我试图测试触发器中哪些列已更新。我知道可以使用UPDATE()函数,如

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;

每次只测试Column1时,即使更新行时所有三列都已更新,其他列也会被忽略。

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

2 个答案:

答案 0 :(得分:2)

当然可以。来自Xapian

  

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

示例:

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;

<强> UPDATE()

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

答案 1 :(得分:0)

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

脱离我的头顶......

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

还尽量避免使用游标。通常可以使用基于集合的operaitons。