MySQL – how to simulate enable/disabled triggers

[adsense id=”0514458240″ width=”468″ height=”60″]

MySQL does not provide a way of enabling or disabling triggers natively. Dropping the trigger and recreating it later on is one solution, however, this can be complex and someone could forget to re-create a trigger after an operation has been performed.

An alternative way is to write the trigger with a built in check to see whether it should trigger on not. This paper will provide a scenario and the code which explains this process.

Imagine we have a table emp which has an UPDATE trigger on this table.

mysql> CREATE TABLE emp (name varchar(100), salary decimal(5,0));
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO emp (name, salary) VALUES ('Tom',1000),('Dick', 1500),('Harry', 1500), ('King',2500);
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from emp;
+-------+--------+
| name  | salary |
+-------+--------+
| Tom   |   1000 |
| Dick  |   1500 |
| Harry |   1500 |
| King  |   2500 |
+-------+--------+
4 rows in set (0.00 sec)

Now we create an UPDATE trigger on the emp table which INSERT’s a record into an emp_audit table which tracks all updates on the table.

mysql> CREATE TABLE emp_audit(name varchar(100), salary decimal(5,0), user varchar(100));
Query OK, 0 rows affected (0.01 sec)

mysql> DELIMITER $$
mysql> CREATE TRIGGER emp_upd
    -> BEFORE UPDATE ON emp
    -> FOR EACH ROW
    -> BEGIN
    ->   INSERT INTO emp_audit(name, salary, user) VALUES (OLD.name, OLD.salary, user());
    -> END;
    -> $$
Query OK, 0 rows affected (0.01 sec)

This trigger will fire each time an update is performed on the table.

mysql> SELECT * FROM emp_audit;
Empty set (0.01 sec)

mysql> UPDATE emp SET salary = 1250 WHERE name = 'Tom';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM emp_audit;
+------+--------+--------------------+
| name | salary | user               |
+------+--------+--------------------+
| Tom  |   1000 | user@localhost     |
+------+--------+--------------------+
1 row in set (0.01 sec)

mysql> DROP TRIGGER emp_upd;
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER $$
mysql> CREATE TRIGGER emp_upd
    -> BEFORE UPDATE ON emp
    -> FOR EACH ROW
    -> BEGIN
    ->   IF @emp_trigger IS NULL OR @emp_trigger = 1 THEN
    ->     INSERT INTO emp_audit(name, salary, user) VALUES (OLD.name, OLD.salary, user());
    ->   END IF;
    -> END;
    -> $$
Query OK, 0 rows affected (0.01 sec)

The new trigger is searching for a session variable @emp_trigger. If this does not exist OR if it does exist and the value is set to 1 then we run the code within the trigger.

mysql> UPDATE emp SET salary = 1750 WHERE name = 'Harry';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM emp_audit;
+-------+--------+--------------------+
| name  | salary | user               |
+-------+--------+--------------------+
| Tom   |   1000 | rcashell@localhost |
| Harry |   1500 | rcashell@localhost |
+-------+--------+--------------------+
2 rows in set (0.00 sec)

Now let’s disable the trigger code by setting the session variable @emp_trigger to 0

mysql> SET @emp_trigger = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE emp SET salary = 1500 WHERE name = 'King';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM emp_audit;
+-------+--------+--------------------+
| name  | salary | user               |
+-------+--------+--------------------+
| Tom   |   1000 | rcashell@localhost |
| Harry |   1500 | rcashell@localhost |
+-------+--------+--------------------+
2 rows in set (0.00 sec)

You can see that the trigger code did not run. To re-enable the trigger code set @emp_trigger to 1

mysql> SET @emp_trigger = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE emp SET salary = salary + 250;
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0

mysql> SELECT * FROM emp_audit;
+-------+--------+--------------------+
| name  | salary | user               |
+-------+--------+--------------------+
| Tom   |   1000 | rcashell@localhost |
| Harry |   1500 | rcashell@localhost |
| Tom   |   1250 | rcashell@localhost |
| Dick  |   1500 | rcashell@localhost |
| Harry |   1750 | rcashell@localhost |
| King  |   1500 | rcashell@localhost |
+-------+--------+--------------------+
6 rows in set (0.00 sec)

Follow us on Twitter for more useful articles.