The Database Design Resource Center

MySQL Triggers:
Auto-generate additional information in the database

MySQL Triggers are one of the newer features in MySQL that are helping to make it a viable alternative for large enterprise applications. Not too long ago, those who made their livings using big commercial databases like Oracle and DB2 pointed out that MySQL was a nice, fast little database but lacked important feature like stored procedures, transactions, and triggers. As of version 5.0 of MySQL, these features can be crossed off of that list.

So, what are MySQL triggers, and why does MySQL's ability to use them make it more attractive to serious database users?

Simply put, triggers are small programs that are stored in the database itself, and are activated by database events which often originate at the application layer. These precipitating database events are UPDATE, DELETE or INSERT queries. The trigger itself may execute before or after the query that initiates it.

Triggers are often used to maintain the integrity of data across tables of an application. When a user on a website makes a purchase, for example, the first action that occurs in the database may be that a credit is inserted into an accounting table.

By way of a trigger this action could initiate a chain reaction of events in other tables throughout the application. The product count of an item could be decremented in an inventory table, a debit deducted from a customer's account balance in another table, a store credit applied to yet another table.

You may say that you have been doing this all along in your applications using PHP or Perl or Python or ASP code. What's the big deal about using MySQL triggers? Well, there are some advantages to using triggers over application code for maintaining integrity of data across tables. A trigger generally performs the types of tasks described faster than application code, and and can be activated easily and quickly behind the scenes and does not need to be a part of your application code.

This saves time and spares you from redundant coding. If you ever port your application to another language, chances are your triggers can stay in place without modification, along with your tables and other database objects.

To demonstrate how MySQL triggers work, let's set up two simple tables on a database we'll call “sales_records” that have data that is interdependent.

Imagine a database that tracks the sales records of three salespeople at a department store. They work in the electronics department selling things like TVs , stereos, and MP3 players.

We have the main table that keeps a record of each sale made. It records the amount of the sale (sale_amt), the date (date), the name of the salesman (name), his id number (employee_id), and the product id (prod_id). We'll call this table (cleverly enough) “sales”.

In the second table, we want to keep some data that will allow us to easily keep track of how each salesperson is doing. It will include the salesperson's id (employee_id), name (name), total number of sales (total_sales), and a column that keeps each salesperson's average amount per sale (ave_sale). We want to see who's moving the high-end items. We'll call this table “performance”.

Now comes the hard part. As I mentioned, triggers are database objects just as tables are. Triggers, however, are able to execute procedural code that modifies data in your tables. In this case, we want our trigger to fire before any INSERT statement that executes in the sales table. When a sale record is inserted in the sales table, the salesperson's totals must be updated in the performance table.

The following code can be typed in your favorite text editor and pasted into your konsole at the MySQL prompt. Before you do that though, you want to execute this line:

mysql: Delimiter $$

Our procedural code uses semicolons at the end of statements, so we need to set a different delimiter to let MySQL know when our code block is over, and so that it doesn't stop processing our block when it hits a semicolon. Keep in mind that after you finish your block you will have to set the delimiter back to the semicolon, or end any subsequent commands with the new delimiter. For example if you made errors in your CREATE TRIGGER block and want to delete it, DROP TRIGGER; won't work unless you set the delimiter back to the semicolon.

Here is the code for the trigger:

MySQL triggers

OK, let's talk about the code. Using the CREATE TRIGGER statement, we've initiated the trigger, naming it 'sales_bi_trg'. MySQL triggers can fire before or after an INSERT, UPDATE or DELETE event. This one fires before any data is inserted in the 'sales' table.

The FOR EACH ROW clause signifies that the block will act on each row that meets the criteria of our SQL statements. The keywords BEGIN and END enclose the trigger statements that will execute when the trigger fires.

There are two variables declared. The first is 'num_row' which checks to see if the employee has who has made the sale that is to be entered, has had a sale entered in the performance table previously. If there are no employee_id's that match, then this is the employee's first sale, and this meets the 'ELSE' condition of our “IF' statement.

This data will be entered as an insert in the performance table rather than an update. If the 'num_row' is greater than 0, then the performance table will be updated. The second variable, 'tot_rows', is a count of how many sales the employee has in the 'sales' table.

This value is used to calculate the employee's average sale. The count is being done before the sale is inserted in the sale table, so we have to add one to it. When the 'performance' table is updated the average sale = total_sales/(tot_rows+1).

If our MySQL trigger is working correctly, the 'performance' table will keep a running total of each salespersons total sales, and also the average amount of their total sales. It will do this independently of your application code and be portable to any application platform.

To give it a whirl, insert some data into the 'sales' table and monitor the content of the 'performance' table. Here is the statement:

MySQL triggers

Change the numbers and names and try it a few times. (Remember, an employee keeps the same employee_id number for each of his sales.) If you're feeling adventurous, start thinking about how the MySQL trigger would have to be extended to account for UPDATE and DELETE statements on the 'sales' table.

Return to MySQL DBA

Exclusive interviews with:
Steven Feuerstein, PLSQL expert
Donald Burleson, Top IT consultant

Free eBook

Subscribe to my newsletter and get my ebook on Entity Relationship Modeling Principles as a free gift:

What visitors say...

"I just stumbled accross your site looking for some normalization theory and I have to say it is fantastic.

I have been in the database field for 10+ years and I have never before come across such a useful site. Thank you for taking the time to put this site together."

Mike, USA

Read more Testimonials

Database Normalization eBook:

Database Normalization eBook

Copyright © /
All rights reserved.
All information contained on this website is for informational purposes only.
Disclaimer: does not warrant any company, product, service or any content contained herein.

Return to top

Copyright acknowledgement note:

The name Oracle is a trademark of Oracle Corporation.
The names MS Access/MS SQL Server are trademarks of Microsoft Corporation.
Any other names used on this website may be trademarks of their respective owners, which I fully respect.