【问题标题】:Get OLD Value in MySQL Trigger AFTER Update Statement在更新语句后获取 MySQL 触发器中的 OLD 值
【发布时间】:2013-07-14 21:57:59
【问题描述】:

我有以下 MySQL 触发器

SET @iUserId = OLD.LastChangedBy; 

IF NOT NEW.LastChangedBy <=> OLD.LastChangedBy THEN
    SET @iUserId = NEW.LastChangedBy;
END IF;

IF NOT NEW.BookingId<=> OLD.BookingId THEN
    INSERT INTO AuditTrail VALUES (UUID(),@iUserId,'UPDATE','Booking', OLD.BookingId,'BookingType ',OLD.BookingType ,NEW.BookingType ,NOW());
END IF;

这被称为 CREATE TRIGGER Booking_AUPD 更新后预订每一行

我遇到的问题是如何在 AFTER UPDATE 触发器中获取 OLD 字段值?

【问题讨论】:

  • 不清楚你在问什么。要引用 UPDATE 之前的列值,请在 AFTER UPDATE 触发器中引用 OLD.col_name,就像您的示例代码对 OLD.LastChangedByOLD.BookingID 等的引用所做的那样。跨度>
  • 是的。我更新了字段 BookingType,我需要在 AFTER UPDATE 触发器中获取 BookingType 的 OLD 值。这可能吗?
  • 是的,触发器主体中对OLD.BookingType 的引用将返回行的BookingType 列的值,就像执行更新语句之前一样。该引用位于 INSERT 语句的 values 子句中。 (我仍然不能理解你在问什么。我们注意到只有在 BookingId 列的 NEW 和 OLD 值不同时才会执行 INSERT。)
  • 是的,这就是我尝试过的,但是在应用触发器时,我得到“INSERT 触发器上没有 OLD 行”
  • 如果您提供返回的实际错误消息,并在问题中提供,这将大大有助于消除歧义并帮助您获得问题的答案。

标签: mysql triggers


【解决方案1】:

UPDATE TRIGGER 中,您可以使用OLD 关键字来访问正在被更新替换的行数据。 NEW 关键字允许访问传入的行数据,如果成功,它将替换旧行。

UPDATE 触发器的示例是:

CREATE TRIGGER upd_check AFTER UPDATE ON SomeTable
    FOR EACH ROW
    BEGIN
       IF (OLD.LastChangedBy <> NEW.LastChangedBy) THEN
         INSERT INTO AuditSomeTable(ID, LastChangedBy) 
         VALUES (OLD.ID, OLD.LastChangedBy);
       END IF;
    END;

SQLFiddle这里

根据创建的触发器类型,OLDNEW 行可能对您不可用:

插入触发器

  • 只能访问NEW 伪行。

更新触发器

  • 访问NEWOLD 伪行

删除触发器

  • 只能访问OLD 伪行

INSERT 触发器上没有 OLD 行,DELETE 触发器上也没有 NEW 行。

OP 的问题

OP没有提供实际代码,以及cmets中提到的错误信息:

INSERT 触发器中没有 OLD 行

表示 OP 无意中创建了一个 INSERT TRIGGER 而不是问题中指出的 UPDATE TRIGGERINSERT 触发器没有 OLD 伪表。

【讨论】:

    【解决方案2】:

    出错的最可能解释

    "There is no OLD row in on INSERT trigger"
    

    是您正在执行创建AFTER INSERT 触发器的语句,而不是创建AFTER UPDATE 触发器。

    由于该行在 INSERT 之前存在,因此您无法从该行引用 OLD 值的原因是该行在 INSERT 之前不存在。

    【讨论】:

      【解决方案3】:

      在触发器正文中,OLD 和 NEW 关键字使您能够访问受触发器影响的行中的列。 OLD 和 NEW 是 MySQL 对触发器的扩展;它们不区分大小写。

      在 INSERT 触发器中,只能使用 NEW.col_name;没有旧行。在 DELETE 触发器中,只能使用 OLD.col_name;没有新行。在 UPDATE 触发器中,您可以使用 OLD.col_name 引用更新前的行列,使用 NEW.col_name 引用更新后的行列。

      【讨论】:

        【解决方案4】:

        如果我没听错你的问题..

        答案是否定的!您不能在 AFTER UPDATE 触发器中包含 OLD.col_name。

        供您在 mysql 参考手册中参考,它明确规定:

        在 INSERT 触发器中,只能使用 NEW.col_name;没有旧行。在 DELETE 触发器中,只能使用 OLD.col_name;没有新行。在 UPDATE 触发器中,您可以使用 OLD.col_name 引用更新前的行列,使用 NEW.col_name 引用更新后的行列。

        Trigger Syntax

        【讨论】:

          【解决方案5】:

          这是我在更新某些列值时触发器如何工作的完整代码

          DELIMITER $$
          
          CREATE TRIGGER `salestatus_after_update` AFTER UPDATE ON `salesdata`
           FOR EACH ROW BEGIN
          
                  IF NEW.sale_status <> OLD.sale_status THEN
                      SET @changetype = 'Sale Status Updated';
                  ELSE
                      SET @changetype = 'Sale Edited';
                  END IF;
          
                  INSERT INTO sales_notification (sale_id, changetype, notify_to, old_value, new_value) VALUES (NEW.id, @changetype, NEW.submit_by, OLD.sale_status, NEW.sale_status);
          
              END$$
          
          DELIMITER ;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-07-20
            • 2013-09-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多