MySQL Triggers Tutorial
September 14, 2006 – 2:34 pmIf you’ve worked with any of the commerical databases other than MySQL, you may have already had some experience with triggers.
I’m glad that the MySQL developers finally managed to squeeze in this extremely important feature. I no longer dread trying to defend MySQL from the Microsoft and Oracle developers who have had triggers for so many years.
I’ll use the example off the MySQL website (explained below in detail). I’ll assume you know how to create a table. If not, please read up on that first.
CREATE TABLE test1(a1 INT);
CREATE TABLE test2(a2 INT);
CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE test4(
a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
b4 INT DEFAULT 0
);DELIMITER |
CREATE TRIGGER testref BEFORE INSERT ON test1
FOR EACH ROW BEGIN
INSERT INTO test2 SET a2 = NEW.a1;
DELETE FROM test3 WHERE a3 = NEW.a1;
UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
END;
|DELIMITER ;
First, we need to change the end of line delimiter. We do this because the statements in the trigger need to end in a semicolon, this is explained further below. This is simple:
DELIMITER |
Next, we specify the action and table for this trigger. In this example, the table is “test1″, and the trigger will execute before any inserts.
CREATE TRIGGER testref BEFORE INSERT ON test1
We specify the following line to make sure if we’re doing a batch update it’ll apply the trigger to each row inserted.
FOR EACH ROW BEGIN
Now we can specify the actions that will occur as the trigger. We use the keywords NEW and OLD to reference the columns in the row. On an INSERT, there are no OLD columns.
INSERT INTO test2 SET a2 = NEW.a1;
DELETE FROM test3 WHERE a3 = NEW.a1;
UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
We’re done – end the trigger. To finish this single statement (because this entire trigger is really 1 statement, remember we changed our end of statement delimiter) we end it with the |
END;
|
We can now change back the end of line delimiter to a semi-colon.
DELIMITER ;
You will now have a trigger on the table ‘test1′ that occurs on every insert.
A few notes:
As of MySQL 5, triggers on DELETES will not run if you delete via cascading foreign keys.
On an INSERT, you can only use NEW for column values. On a DELETE, you must use OLD.
I will post another tutorial soon on the practical use of triggers in web development. I hope this helps someone.



34 Responses to “MySQL Triggers Tutorial”
Good job! i always wanted to know how this stuff.
By Sunny on Sep 15, 2006
I’d love to see this article on http://www.eioba.com
By Riki on Sep 19, 2006
i want to be reset a table at one hour (and a day) how can i do this
By fatih akkoyun on Sep 19, 2006
You can reset a table using cron jobs. i am assuming you are simply asking for truncating a table automatically.
By Sunny on Sep 19, 2006
its not working for me, when i place semicolin at the end of statment it terminates the mysql prompt giving error. mysql version 5.0.18. cam someone help
By mateen on Oct 2, 2006
You need to use
DELIMITER |
at the beginning, so the semicolons don’t end the statement.
By jon on Oct 2, 2006
yes i want this –>truncating a table automatically
trigger can’t do or i can’t did with trigger
so what is the cron jobs
By fatih akkoyun on Oct 12, 2006
“I’m glad that the MySQL developers finally managed to squeeze in this extremely important feature. I no longer dread trying to defend MySQL from the Microsoft and Oracle developers who have had triggers for so many years.”
Yes triggers are nice. But if you dont know what you are doing, you can cause MAJOR overhead on your server. Ive been working with mysql 3.23.55 for a while (based on our business model upgrading is a slow process). So when you are trying to defend mysql from the evil empires, Keep in mind that they are trying to sell more licenses for servers and they will always tell you to use them.
By Chuck on Jan 2, 2007
Hi,
I created a create database script with create table and lots of insert statements inside. At the end of the file I added the create procedure and create trigger statements using the delimiter $$ statement, but when I try to run the batch with mysql -uroot -pxxx -e “source createdb.sql”, the batch fails at the first delimiter statement. Also want to mention, that the statements are working from mysql monitor client.
If I dump my database with triggers and strored procedures it will be filled with a lot of /*50003 CREATE */ style comments, which are working but makes the code unreadable and hard to maintain.
If you know how to include the Create Trigger statements into a large sql file and make them work, please let me know.
Thanks.
By Csaba on Feb 28, 2007
Thanks a lot!
By JP on Mar 21, 2007
I understand the basics of triggers, but is this a certain programming language? I would like to know what syntax the triggers use so I can make more complex triggers.
By Travis on Mar 22, 2007
hi there.will like to know how to capture the response, using php,generated by the triggers.is there exists such a way because most of the time we dont connect directly but using some other language
By ashu on Apr 22, 2007
Triggers do not produce a response, or any have any output.
By jon on Jun 3, 2007
Jon, Ashu,
Triggers can be used to generate an output. You can include a SELECT statment in your trigger, either as a simple string
SELECT “Task Completed”;
or a more complex table query
SELECT * FROM `my_tbl` WHERE `my_tbl.date`
By Dan on Jun 5, 2007
Be careful. Adding triggers in MySQL (as of 5.1) causes huge overhead and will slow performance to a point that is untenable for most moderate traffic servers. Having a feature is one thing, having a feature that performs like other DBs is quite another.
By Erick on Aug 9, 2007
thank u …thank u for letting me know the basics of triggers…regarding their creation…..syntax….working and all…..looking forward for another tutorial post!!….
By Sri harsha on Oct 5, 2007
I am new to triggers and get the syntax but have a hard time applying this knowledge!!
I have a an auction database, and i need to write a trigger that verifies that the next bid placed is larger than the current high bid. Can anyone help me?
By Ewa on Nov 9, 2007
Hey Ewa:
You’re probably going to want to use a stored procedure to check that. According to the MySQL boards, there’s no clean way to abort a query in mysql using a trigger. Read through this thread for more info:
http://forums.mysql.com/read.php?99,55108,55108#msg-55108
By jon on Dec 2, 2007
Hey Everyone…
I’ve been searching all over for the answer to this one. If you have the answer, it would help me out a lot!
Using MySQL triggers, I want to sync content between two tables; I have table “user” and table “users”, each have similar columns “last_name” “first_name” “user_id” …etc, and when a row gets written to table “users”, I wanted that record to be replicated to “user”.
How do I write this trigger? I know, it’s anti-normalization, but it will really help me out in the long run.
Thanks all!
By Ryan on Dec 20, 2007
Hey Ryan
In this case, I’d recommend calling a stored procedure to perform this type of replication.
– almost identical tables. copying data from user to users
create table user (userid int auto_increment primary key, fname varchar(10), lname varchar(10));
create table users (userid int primary key, fname varchar(10), lname varchar(10));
delimiter |
create procedure copy_row(uid int)
begin
INSERT INTO users (userid, fname, lname)
SELECT userid, fname, lname from user WHERE userid = uid;
end;
|
delimiter ;
mysql> insert into user (fname, lname) values (’joe’, ’smith’), (’steve’, ‘brown’),(’jon’, ‘haddad’);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> call copy_row(1);
Query OK, 1 row affected (0.01 sec)
mysql> select * from user;
+——–+——-+——–+
| userid | fname | lname |
+——–+——-+——–+
| 1 | joe | smith |
| 2 | steve | brown |
| 3 | jon | haddad |
+——–+——-+——–+
3 rows in set (0.00 sec)
mysql> select * from users;
+——–+——-+——-+
| userid | fname | lname |
+——–+——-+——-+
| 1 | joe | smith |
+——–+——-+——-+
1 row in set (0.00 sec)
If you really want to do this with a trigger, you can do something like this:
delimiter |
create trigger user_ins AFTER insert on user
for each row begin
call copy_row(NEW.userid);
end;
|
create trigger user_upd AFTER update on user
for each row begin
call copy_row(NEW.userid);
end;
|
create trigger user_del AFTER delete on user
for each row begin
delete from users WHERE userid = OLD.userid;
end;
|
delimiter ;
mysql> insert into user (fname, lname) values (’octavious’, ‘jones’);
Query OK, 1 row affected (0.00 sec)
mysql> select * from users;
+——–+———–+——-+
| userid | fname | lname |
+——–+———–+——-+
| 1 | joe | smith |
| 4 | octavious | jones |
+——–+———–+——-+
2 rows in set (0.00 sec)
Hopefully this helps.
By jon on Dec 21, 2007
Is it possible to generate emails with triggers? for example if a user is added to a database that the admin gets an email with the userdata? (I know this can easily be done with PHP, but I want to know if it can be done with triggers in MySQL.
By Raymond on Apr 9, 2008
To my knowledge, MySQL cannot send out emails. This question was brought up on the MySQL list in 2005, found here: http://forums.mysql.com/read.php?99,33635,33651#msg-33651
I believe it is possible in Postgres.
By jon on Apr 11, 2008
mysql> delimiter ;
mysql> delimiter //
mysql> create procedure mostrar1(prov varchar(15))
-> begin
-> select p.id_producto,p.des_producto,pr.des_proveedor
-> from tb_producto p,tb_proveedor pr where p.id_proveedor=pr.id_proveedor;
-> end
-> //
delimiter ;
call mostrar1();
By ketty on Jun 13, 2008
how to trigger between two database??
By Dio on Nov 10, 2008
Dio:
If you’re talking about 1 machine with multiple schemas: did you try prefixing the database name before your table?
If you’re talking about 2 different database servers, I don’t think you can do that with MySQL.
By jon on Nov 11, 2008
Hi, very good explanation of all the examples and theory you give to the folk. Thank you for the good job.
I have a question that I cannot resolve yet and I hope you can help me out.
I’m using MySQL 5.1.29 RC and I wrote a database with some tables one of them is called “users”. I want to create a trigger before insert on the table “login”. ie. before inserting any value in the table “login” I want to insert some values in another table called “users”, my code is below:
First I created my tables with the following syntax:
create users
(
userID int unsigned not null auto_increment primary key,
company char(50)
)type=innodb;
create login
(
userID int unsigned not null,
username char(100),
password char(100) not null unique
)type=innodb;
After That I created the trigger:
create triger test_trg before insert on login
for each row begin
insert into users values(NULL,’ ‘);
end;
result: it doesn’t work, I have tried using also those syntaxes:
create triger test_trg before insert on login
for each row begin
insert into users values(’0′,’ ‘);
end;
create triger test_trg before insert on login
for each row begin
insert into users values(0);
end;
create triger test_trg before insert on login
for each row begin
insert into users set userID = ‘0′;
insert into users set company = ’somecmpy’;
end;
create triger test_trg before insert on login
for each row begin
insert into users set userID = 0;
insert into users set company = ’somecmpy’;
end;
Result: I couldn’t create my trigger yet.
Again:
I want to create a trigger before insert on the table “login”. ie. before inserting any value in the table “login” I want to insert a new value “userID” for the table “users”. Can you give me any clue about the problem. Thanks in advance.
By Alexei Larramendi on Dec 1, 2008
I just followed above article and is help ful to me. I m first time using trigger, it is perfect article for a bigainer.
By Arun Patjosy on Jan 5, 2009
Hey Everyone…
I’ve been searching all over for the answer to this one. If you have the answer, it would help me out a lot!
Using MySQL triggers for SMS Gateway, I have table “inbox” and table “voting”, I want to input table “voting” automatictly whenever SMS come (store in table inbox)I try to creat script and try to sens messange like this “man 5 3 4 10 20 30 40 50 60 70 80 90 100 11 22″:
CREATE TRIGGER smsin AFTER INSERT ON inbox
FOR EACH ROW
$row = array(”TextDecoded”);
$cut=explode(” “,$row);
if ($cut[1]=’man’)
{
$query = mysql_query (”insert into voting1 values
(’ ‘,’$cut1[0]‘,’$cut1[1]‘,’$cut1[2]‘,’$cut1[3]‘,’$cut1[4]‘,
‘$cut1[5]‘,’$cut1[6]‘,’$cut1[7]‘,’$cut1[8]‘,’$cut1[9]‘,
‘$cut1[10]‘,’$cut1[11]‘,’$cut1[12]‘,’$cut1[13]‘,’$cut1[14]‘,’$cut1[15]‘,’$cut1[16]‘)”);
}
else
{
$query = mysql_query (”insert into voting2 values
(’ ‘,’$cut1[0]‘,’$cut1[1]‘,’$cut1[2]‘,’$cut1[3]‘,’$cut1[4]‘,
‘$cut1[5]‘,’$cut1[6]‘,’$cut1[7]‘,’$cut1[8]‘,’$cut1[9]‘,
‘$cut1[10]‘,’$cut1[11]‘,’$cut1[12]‘,’$cut1[13]‘,’$cut[14]‘)”);
}
Buat it didn’t run… could anybody can help ?
I Really appreciate.
Thanks all!
By Dani Yusuf on Feb 1, 2009
Hey, everyone
Can you help me?
I have problem. I have trigger that definer is my own create. When i disable my own create, my trigger is error. I want alter my trigger with other definer that I must not drop it then recreate.
By cruise on Mar 3, 2009
hi. i have a question. how to ALTER TABLE in CREATE TRIGGER? i want to ADD ROW in TABLE
for example:
ALTER TABLE `faqs` ADD ‘question_’+NEW.code INT NOT NULL;
ALTER TABLE `faqs` ADD ‘answer_’+NEW.code INT NOT NULL;
By tsogoo on Jun 22, 2009
Thanks for the tutorial. Haven’t worked much with triggers and this was helpful.
By shaun on Sep 24, 2009
Thank you so much for explaining this, i never properly read the docs. Have been using oracle too much.
By Crisitan on Feb 21, 2010