sql >> データベース >  >> RDS >> Mysql

行が変更された場合にのみ、更新後にMySQLトリガー

    回避策として、タイムスタンプ(新旧)を使用してチェックすることもできますが、そのタイムスタンプはではありません。 行に変更がない場合に更新されます。 (おそらくそれが混乱の原因ですか?これは「更新時」とも呼ばれますが、変更が発生しない場合は実行されないため)1秒以内の変更では、トリガーのその部分は実行されませんが、場合によっては問題ない可能性があります(とにかく速い変更を拒否するアプリケーションがある場合のように。)

    たとえば、

    ではなく
    IF NEW.a <> OLD.a or NEW.b <> OLD.b /* etc, all the way to NEW.z <> OLD.z */ 
    THEN  
      INSERT INTO bar (a, b) VALUES(NEW.a, NEW.b) ;
    END IF
    

    使用できます

    IF NEW.ts <> OLD.ts 
    THEN  
      INSERT INTO bar (a, b) VALUES(NEW.a, NEW.b) ;
    END IF
    

    そうすれば、スキームを更新するたびにトリガーを変更する必要はありません(質問で言及した問題)。

    編集:完全な例を追加

    create table foo (a INT, b INT, ts TIMESTAMP);
    create table bar (a INT, b INT);
    
    INSERT INTO foo (a,b) VALUES(1,1);
    INSERT INTO foo (a,b) VALUES(2,2);
    INSERT INTO foo (a,b) VALUES(3,3);
    
    DELIMITER ///
    
    CREATE TRIGGER ins_sum AFTER UPDATE ON foo
        FOR EACH ROW
        BEGIN
            IF NEW.ts <> OLD.ts THEN  
                INSERT INTO bar (a, b) VALUES(NEW.a, NEW.b);
            END IF;
        END;
    ///
    
    DELIMITER ;
    
    select * from foo;
    +------+------+---------------------+
    | a    | b    | ts                  |
    +------+------+---------------------+
    |    1 |    1 | 2011-06-14 09:29:46 |
    |    2 |    2 | 2011-06-14 09:29:46 |
    |    3 |    3 | 2011-06-14 09:29:46 |
    +------+------+---------------------+
    3 rows in set (0.00 sec)
    
    -- UPDATE without change
    UPDATE foo SET b = 3 WHERE a = 3;
    Query OK, 0 rows affected (0.00 sec)
    Rows matched: 1  Changed: 0  Warnings: 0
    
    -- the timestamo didnt change
    select * from foo WHERE a = 3;
    +------+------+---------------------+
    | a    | b    | ts                  |
    +------+------+---------------------+
    |    3 |    3 | 2011-06-14 09:29:46 |
    +------+------+---------------------+
    1 rows in set (0.00 sec)
    
    -- the trigger didn't run
    select * from bar;
    Empty set (0.00 sec)
    
    -- UPDATE with change
    UPDATE foo SET b = 4 WHERE a=3;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    -- the timestamp changed
    select * from foo;
    +------+------+---------------------+
    | a    | b    | ts                  |
    +------+------+---------------------+
    |    1 |    1 | 2011-06-14 09:29:46 |
    |    2 |    2 | 2011-06-14 09:29:46 |
    |    3 |    4 | 2011-06-14 09:34:59 |
    +------+------+---------------------+
    3 rows in set (0.00 sec)
    
    -- and the trigger ran
    select * from bar;
    +------+------+---------------------+
    | a    | b    | ts                  |
    +------+------+---------------------+
    |    3 |    4 | 2011-06-14 09:34:59 |
    +------+------+---------------------+
    1 row in set (0.00 sec)
    

    タイムスタンプの処理に関するmysqlの動作により、機能しています。タイムスタンプは、更新で変更が発生した場合にのみ更新されます。

    ドキュメントはこちら:
    https:// dev .mysql.com / doc / refman / 5.7 / en / timestamp-initialization.html

    desc foo;
    +-------+-----------+------+-----+-------------------+-----------------------------+
    | Field | Type      | Null | Key | Default           | Extra                       |
    +-------+-----------+------+-----+-------------------+-----------------------------+
    | a     | int(11)   | YES  |     | NULL              |                             |
    | b     | int(11)   | YES  |     | NULL              |                             |
    | ts    | timestamp | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
    +-------+-----------+------+-----+-------------------+-----------------------------+
    


    1. OracleでORDERを使用してINSERT

    2. 生命保険データモデル

    3. SQL Serverで大文字を小文字に変換する方法– LOWER()

    4. PHP MYSQL UPDATEが存在する場合、またはINSERTが存在しない場合は?