Trigger: Referencing updated attribute

2019-08-31 07:18发布

问题:

I have a Trigger on UPDATE.

What is the correct procedure for referencing attribute from the table that is not updated by the UPDATE SQL command? Is the attribute still in the UPDATE variable? I would like to get the value of that attribute for the updated row.

回答1:

You can access a values of a column before update and after update in MySQL by using keywords OLD and NEW.

For example if you want to determine whether a value of a column actually has been changed during updated you can do

IF NOT OLD.column_name <=> NEW.column_name THEN
    -- do something here
END IF;

Note: <=> is NULL-safe comparison operator in MySQL

BTW: There is no UPDATED virtual table in MySQL. It's from SQL Server.

Here is a SQLFiddle demo. Note that even though update affected all records in the table, only one message has been logged in log table. It's because value for a row with id 2 in the end stayed the same.


UPDATE: to keep your finished flag in sync you need triggers for all events (insert, update, delete).

DELIMITER //
CREATE TRIGGER tg_ai_event
AFTER INSERT ON event
FOR EACH ROW
BEGIN
  UPDATE activity a
     SET status = (EXISTS(SELECT * 
                            FROM event 
                           WHERE activity = a.activity_id
                             AND done = 0))
   WHERE activity_id = NEW.activity;
END//

CREATE TRIGGER tg_ad_event
AFTER DELETE ON event
FOR EACH ROW
BEGIN
  UPDATE activity a
     SET status = (EXISTS(SELECT * 
                            FROM event 
                           WHERE activity = a.activity_id 
                             AND done = 0))
   WHERE activity_id = OLD.activity;
END//

CREATE TRIGGER tg_au_event
AFTER UPDATE ON event
FOR EACH ROW
BEGIN
  IF NOT OLD.activity <=> NEW.activity THEN
    -- if activity id was changed for an event then clculate finished flag
    -- for both old and new activity id
    UPDATE activity a
       SET status = (EXISTS(SELECT * 
                              FROM event 
                             WHERE activity = a.activity_id 
                               AND done = 0))
     WHERE activity_id IN(OLD.activity, NEW.activity);
  ELSE
    -- otherwise calculate finished flag only if done flag is changed 
    IF NOT OLD.done <=> NEW.done THEN
      UPDATE activity a
         SET status = (EXISTS(SELECT * 
                                FROM event 
                               WHERE activity = a.activity_id 
                                 AND done = 0))
       WHERE activity_id = NEW.activity;
    END IF;
  END IF;
END//
DELIMITER ;

Here is SQLFiddle demo