Frank Mash did some testing with triggers and inspired me to try to create a log table based on triggers. This also answers his question “After playing earlier with triggers, I wanted to see whether one can update another table using MySQL triggers. I tried something like … but it didn’t work. Is it possible or am I shooting in the dark here?” with a clear yes!
First I created a data and a log table:
mysql> CREATE TABLE data_table (
-> id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> d1 VARCHAR(200) NOT NULL UNIQUE,
-> d2 DECIMAL(9,2) NOT NULL) ENGINE=InnoDB;
Query OK, 0 rows affected (0.02 sec)
mysql> CREATE TABLE log_table (
-> id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> id_data INT UNSIGNED NOT NULL,
-> old_d1 VARCHAR(200) NULL,
-> new_d1 VARCHAR(200) NULL,
-> old_d2 DECIMAL(9,2) NULL,
-> new_d2 DECIMAL(9,2) NULL,
-> kind_of_change ENUM('insert', 'update', 'delete') NOT NULL,
-> ts TIMESTAMP NOT NULL) ENGINE=InnoDB;
Query OK, 0 rows affected (0.02 sec)
Then I needed three triggers to log each kind of modification: insert, update and delete. I used after triggers to make sure that there’s only a log entry, if the modification really worked:
mysql> DELIMITER //
mysql> DROP TRIGGER test.data_table_ai//
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TRIGGER test.data_table_ai
-> AFTER INSERT ON test.data_table
-> FOR EACH ROW
-> BEGIN
->
-> INSERT INTO log_table
-> (id_data, old_d1, new_d1,
-> old_d2, new_d2,
-> kind_of_change, ts)
-> VALUES
-> (new.id, NULL, new.d1,
-> NULL, new.d2, 'insert', now());
->
-> END //
Query OK, 0 rows affected (0.02 sec)
mysql> DROP TRIGGER test.data_table_au//
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TRIGGER test.data_table_au
-> AFTER UPDATE ON test.data_table
-> FOR EACH ROW
-> BEGIN
->
-> INSERT INTO log_table
-> (id_data, old_d1, new_d1,
-> old_d2, new_d2,
-> kind_of_change, ts)
-> VALUES
-> (new.id, old.d1, new.d1,
-> old.d2, new.d2, 'update', now());
->
-> END //
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TRIGGER test.data_table_ad//
Query OK, 0 rows affected (0.02 sec)
mysql> CREATE TRIGGER test.data_table_ad
-> AFTER DELETE ON test.data_table
-> FOR EACH ROW
-> BEGIN
->
-> INSERT INTO log_table
-> (id_data, old_d1, new_d1,
-> old_d2, new_d2,
-> kind_of_change, ts)
-> VALUES
-> (old.id, old.d1, NULL,
-> old.d2, NULL, 'delete', now());
->
-> END //
Query OK, 0 rows affected (0.02 sec)
mysql> DELIMITER ;
Finally, I simply inserted a few records and updated and deleted some of them:
mysql> INSERT INTO data_table (d1, d2) VALUES ('Markus', 534.12);
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO data_table (d1, d2) VALUES ('Frank', 210.33);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO data_table (d1, d2) VALUES ('Charles', 1047.11);
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE data_table SET d2=492.11 WHERE d1='Markus';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> DELETE FROM data_table WHERE d1='Charles';
Query OK, 1 row affected (0.00 sec)
So here’s what the tables look like:
mysql> SELECT * FROM data_table;
+----+--------+--------+
| id | d1 | d2 |
+----+--------+--------+
| 1 | Markus | 492.11 |
| 2 | Frank | 210.33 |
+----+--------+--------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM log_table\G
*************************** 1. row ***************************
id: 1
id_data: 1
old_d1: NULL
new_d1: Markus
old_d2: NULL
new_d2: 534.12
kind_of_change: insert
ts: 2006-01-25 15:47:43
*************************** 2. row ***************************
id: 2
id_data: 2
old_d1: NULL
new_d1: Frank
old_d2: NULL
new_d2: 210.33
kind_of_change: insert
ts: 2006-01-25 15:48:10
*************************** 3. row ***************************
id: 3
id_data: 3
old_d1: NULL
new_d1: Charles
old_d2: NULL
new_d2: 1047.11
kind_of_change: insert
ts: 2006-01-25 15:48:27
*************************** 4. row ***************************
id: 4
id_data: 1
old_d1: Markus
new_d1: Markus
old_d2: 534.12
new_d2: 492.11
kind_of_change: update
ts: 2006-01-25 15:48:49
*************************** 5. row ***************************
id: 5
id_data: 3
old_d1: Charles
new_d1: NULL
old_d2: 1047.11
new_d2: NULL
kind_of_change: delete
ts: 2006-01-25 15:49:06
5 rows in set (0.00 sec)
Very useful, isn’t it ;)?