129

Is it possible to fire a mysql trigger for both the insert and update events of a table?

I know I can do the following

CREATE TRIGGER my_trigger
    AFTER INSERT ON `table`
    FOR EACH ROW
BEGIN
.....
END //

CREATE TRIGGER my_trigger
    AFTER UPDATE ON `table`
    FOR EACH ROW
BEGIN
.....
END //

But how can I do

CREATE TRIGGER my_trigger
    AFTER INSERT ON `table` AND
    AFTER UPDATE ON `table`
    FOR EACH ROW
BEGIN
.....

Is it possible, or do I have to use 2 triggers? The code is the same for both and I don't want to repeat it.

Adam S-Price
  • 1,898
  • 2
  • 15
  • 21

3 Answers3

147

You have to create two triggers, but you can move the common code into a procedure and have them both call the procedure.

derobert
  • 47,899
  • 11
  • 91
  • 122
  • 3
    Could you give a toy example of this for those of us who are unfamiliar with the syntax? – Zxaos Jul 01 '11 at 00:00
  • 4
    @Zxaos: I'd suggest starting with http://dev.mysql.com/doc/refman/5.1/en/create-procedure.html (which includes some examples) and asking your own question(s) if needed. – derobert Jul 01 '11 at 05:21
  • 2
    It's a pity that we can't use AND/OR operators like in Oracle, even more when we also can't pass by parameter to a procedure the whole variables OLD and NEW. My code will be > 2x – Mikel Nov 26 '13 at 08:13
  • This one's useful for a developer who never compromises on writing a code twice.. – Abdul Saleem Sep 10 '15 at 16:47
  • "strongly recommend not calling any stored procedures from a Trigger" # https://dba.stackexchange.com/questions/10657/call-a-stored-procedure-from-a-trigger – luismartingil Oct 09 '19 at 12:50
  • 1
    @luismartingil there is probably some extra overhead of calling a procedure vs. inlining it. But in exchange you get easier maintenance and a guarantee that the two triggers' code won't accidentally diverge. – derobert Oct 09 '19 at 14:30
52

In response to @Zxaos request, since we can not have AND/OR operators for MySQL triggers, starting with your code, below is a complete example to achieve the same.

1. Define the INSERT trigger:

DELIMITER //
DROP TRIGGER IF EXISTS my_insert_trigger//
CREATE DEFINER=root@localhost TRIGGER my_insert_trigger
    AFTER INSERT ON `table`
    FOR EACH ROW

BEGIN
    -- Call the common procedure ran if there is an INSERT or UPDATE on `table`
    -- NEW.id is an example parameter passed to the procedure but is not required
    -- if you do not need to pass anything to your procedure.
    CALL procedure_to_run_processes_due_to_changes_on_table(NEW.id);
END//
DELIMITER ;

2. Define the UPDATE trigger

DELIMITER //
DROP TRIGGER IF EXISTS my_update_trigger//

CREATE DEFINER=root@localhost TRIGGER my_update_trigger
    AFTER UPDATE ON `table`
    FOR EACH ROW
BEGIN
    -- Call the common procedure ran if there is an INSERT or UPDATE on `table`
    CALL procedure_to_run_processes_due_to_changes_on_table(NEW.id);
END//
DELIMITER ;

3. Define the common PROCEDURE used by both these triggers:

DELIMITER //
DROP PROCEDURE IF EXISTS procedure_to_run_processes_due_to_changes_on_table//

CREATE DEFINER=root@localhost PROCEDURE procedure_to_run_processes_due_to_changes_on_table(IN table_row_id VARCHAR(255))
READS SQL DATA
BEGIN

    -- Write your MySQL code to perform when a `table` row is inserted or updated here

END//
DELIMITER ;

You note that I take care to restore the delimiter when I am done with my business defining the triggers and procedure.

Al Zziwa
  • 977
  • 8
  • 5
  • 1
    What's `IN table_row_id VARCHAR(255)` in this case? I mean how are you defining which row is going to be inserted or updated? – VaTo Feb 25 '16 at 01:04
14

unfortunately we can't use in MySQL after INSERT or UPDATE description, like in Oracle

Jeff_Alieffson
  • 2,454
  • 27
  • 33