You are on page 1of 11

How to Create Scheduled

Events in MySQL
http://www.sitepoint.com/how-to-create-mysql-events/

Craig Buckler

Contributing Editor
Published July 20, 2011
TweetSubscribe
This is the third and last article in a series about database automation with triggers and events. If
youve not done so already, please read How to Create Triggers in MySQL which introduces
many of the concepts discussed here.
An event is similar to a trigger. However, rather than running in response to a data change,
events can be scheduled to run any number of times during a specific period. In effect, its a
database-only cron job.
Events have been supported in MySQL since version 5.1. They are ideal for maintenance tasks
such as data archiving or report generation which can be scheduled during off-peak times.
Our Database Plan
Our blog database has a problem. Old posts are marked as deleted rather than being removed
from the `blog` table. Our table will grow indefinitely and become slower over time. We could
purge the old posts but that would remove them forever. Therefore, well move posts and their
associated audit records to archive tables. The archive tables can grow without affecting the
speed of the main web application and we can undelete old posts if necessary.
Two archive tables are required:
`blog_archive`: identical to the `blog` table except it does not require a deleted flag or an
auto-incrementing ID.
`audit_archive`: identical to the `audit` table except the timestamp is not automatically
generated and it does not require an auto-incrementing ID.
The following SQL creates both tables:

CREATE TABLE `blog_archive` (
`id` mediumint(8) unsigned NOT NULL,
`title` text,
`content` text,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Blog posts archive';
--
CREATE TABLE `audit_archive` (
`id` mediumint(8) unsigned NOT NULL,
`blog_id` mediumint(8) unsigned NOT NULL,
`changetype` enum('NEW','EDIT','DELETE') NOT NULL,
`changetime` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_blog_id` (`blog_id`),
KEY `ix_changetype` (`changetype`),
KEY `ix_changetime` (`changetime`),
CONSTRAINT `FK_audit_blog_archive_id` FOREIGN KEY (`blog_id`)
REFERENCES `blog_archive` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Starting MySQLs Event Scheduler
MySQL events are executed by a special event scheduler thread. Its disabled by default so use
the following MySQL command can determine whether its running:

SHOW PROCESSLIST;
If the scheduler is running, at least two rows will be shown and one will have its user field set to
event_scheduler. If only one row is returned, the scheduler is disabled and events will not run.
You can ensure the scheduler starts when MySQL is launched with the command-line option --
event-scheduler=ON or setting event_scheduler=ON in your MySQL configuration file
(my.cnf or my.ini on Windows).
Alternatively, you can start the scheduler from the MySQL command line:

SET GLOBAL event_scheduler = ON;
Creating an Event
We require a scheduled event which:
Copies posts from `blog` to `blog_archive` when the deleted flag is set to 1.
Copies the associated audit entries for those posts from `audit` to `audit_archive`.
Physically deletes archived posts from the `blog` table. Referential integrity has been defined
with a foreign key so all associated audit entries for those posts will also be removed.
Assuming you have MySQL rights to create events, the basic syntax is:

CREATE EVENT `event_name`
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
DO BEGIN
-- event body
END;
The schedule can be assigned various settings, e.g.
Run once on a specific date/time:
AT YYYY-MM-DD HH:MM.SS
e.g. AT 2011-06-01 02:00.00
Run once after a specific period has elapsed:
AT CURRENT_TIMESTAMP + INTERVAL n [HOUR|MONTH|WEEK|DAY|MINUTE]
e.g. AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
Run at specific intervals forever:
EVERY n [HOUR|MONTH|WEEK|DAY|MINUTE]
e.g. EVERY 1 DAY
Run at specific intervals during a specific period:
EVERY n [HOUR|MONTH|WEEK|DAY|MINUTE] STARTS date ENDS date
e.g. EVERY 1 DAY STARTS CURRENT_TIMESTAMP + INTERVAL 1 WEEK ENDS
2012-01-01 00:00.00
An event is normally dropped once its schedule has expired (ON COMPLETION NOT
PRESERVE). Set ON COMPLETION PRESERVE to prevent that behavior. The MySQL
CREATE EVENT Syntax documentation provides further details.
We can now define our event (remembering to set the DELIMITER first). Well set it to run
every week starting on a Sunday morning:

DELIMITER $$

CREATE
EVENT `archive_blogs`
ON SCHEDULE EVERY 1 WEEK STARTS '2011-07-24 03:00:00'
DO BEGIN

-- copy deleted posts
INSERT INTO blog_archive (id, title, content)
SELECT id, title, content
FROM blog
WHERE deleted = 1;

-- copy associated audit records
INSERT INTO audit_archive (id, blog_id, changetype,
changetime)
SELECT audit.id, audit.blog_id, audit.changetype,
audit.changetime
FROM audit
JOIN blog ON audit.blog_id = blog.id
WHERE blog.deleted = 1;

-- remove deleted blogs and audit entries
DELETE FROM blog WHERE deleted = 1;

END */$$

DELIMITER ;
This is a simple example but you could add more functionality, e.g. only move posts which were
deleted at least 1 month ago and purge all archieved posts over 1 year old. I hope youve enjoyed
this series and are considering database triggers and events in your next project.

Another way to approach this is to use MySql events for scheduling and LOAD DATA INFILE for
importing CSV
Your event code might look like this

DELIMITER $$
CREATE EVENT ev_update_from_csv
ON SCHEDULE EVERY 10 MINUTE
DO BEGIN
-- Import csv into temptable
LOAD DATA INFILE '/path/file.csv'
INTO TABLE temptable
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 LINES;
-- Do other processing and transfer (insert or update) to a factual table here
INSERT INTO realtable (col1, col2, ...)
SELECT (col1, col2, ...)
FROM temptable
-- Clear temptable
TRUNCATE temptable;
END $$
DELIMITER ;

The function accepts 4 parameters:
1. filename (string): Path to csv file. Eg: myfile.csv
2. startRow (int): First row in delete area
3. endRow (int): Last row in delete area
4. inner (boolean): decide whether rows deleted are from inner area or outer area
Now Let us consider various cases. I have a csv file with me named test.csv. Here is the
screenshot of the same.
Example 1:
$status = csv_delete_rows('test.csv', 3, 5, true);
will delete the red part of:

Example 2:
$status = csv_delete_rows('test.csv', 3, 5, false);
will delete the red part of:

Example 3: Like in your situation, if you want to delete the first 100 rows, use this:
$status = csv_delete_rows('test.csv', 0, 100);

function csv_delete_rows($filename=NULL, $startrow=0, $endrow=0, $inner=true)
{
$status = 0;
//check if file exists
if (file_exists($filename)) {
//end execution for invalid startrow or endrow
if ($startrow < 0 || $endrow < 0 || $startrow > 0 && $endrow > 0 && $startrow
> $endrow) {
die('Invalid startrow or endrow value');
}
$updatedcsv = array();
$count = 0;
//open file to read contents
$fp = fopen($filename, "r");
//loop to read through csv contents
while ($csvcontents = fgetcsv($fp)) {
$count++;
if ($startrow > 0 && $endrow > 0) {
//delete rows inside startrow and endrow
if ($inner) {
$status = 1;
if ($count >= $startrow && $count <= $endrow)
continue;
array_push($updatedcsv, implode(',', $csvcontents));
}
//delete rows outside startrow and endrow
else {
$status = 2;
if ($count < $startrow || $count > $endrow)
continue;
array_push($updatedcsv, implode(',', $csvcontents));
}
}
else if ($startrow == 0 && $endrow > 0) {
$status = 3;
if ($count <= $endrow)
continue;
array_push($updatedcsv, implode(',', $csvcontents));
}
else if ($endrow == 0 && $startrow > 0) {
$status = 4;
if ($count >= $startrow)
continue;
array_push($updatedcsv, implode(',', $csvcontents));
}
else if ($startrow == 0 && $endrow == 0) {
$status = 5;
} else {
$status = 6;
}
}//end while
if ($status < 5) {
$finalcsvfile = implode("\n", $updatedcsv);
fclose($fp);
$fp = fopen($filename, "w");
fwrite($fp, $finalcsvfile);
}
fclose($fp);
return $status;
} else {
die('File does not exist');
}
}

Export MySQL table to CSV using PHP

<?php

// Database Connection

$host="localhost";
$uname="root";
$pass="";
$database = "a2zwebhelp";

$connection=mysql_connect($host,$uname,$pass);

echo mysql_error();

//or die("Database Connection Failed");
$selectdb=mysql_select_db($database) or
die("Database could not be selected");
$result=mysql_select_db($database)
or die("database cannot be selected <br>");

// Fetch Record from Database

$output = "";
$table = ""; // Enter Your Table Name
$sql = mysql_query("select * from $table");
$columns_total = mysql_num_fields($sql);

// Get The Field Name

for ($i = 0; $i < $columns_total; $i++) {
$heading = mysql_field_name($sql, $i);
$output .= '"'.$heading.'",';
}
$output .="\n";

// Get Records from the table

while ($row = mysql_fetch_array($sql)) {
for ($i = 0; $i < $columns_total; $i++) {
$output .='"'.$row["$i"].'",';
}
$output .="\n";
}

// Download the file

$filename = "myFile.csv";
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename='.$filename);

echo $output;
exit;

?>
Lets write a simple php program to import data from CSV files or read CSV file using PHP. The following
program will read the csv file and display output in HTML table format. Once you get the data you can
either display it in HTML format or save in your MySql database.


PHP Code
<?php
include( 'FileReader.php' );
include( 'CSVReader.php' );

$reader =& new CSVReader( new FileReader( 'countrylist.csv' ) );
// set the separator as comma
$reader->setSeparator( ',' );
$line = 0; // line tracking

// output
echo '<table cellpadding=2 cellspacing=1 bgcolor="#cdcdcd" border=0>';
while( false != ( $cell = $reader->next() ) ) {
if ( $line == 0 ) {
echo "<tr>\n";
echo "<td style='font: 12px Arial; font-weight: bold' nowrap> # </td>\n";
for ( $i = 0; $i < count( $cell ); $i++ ){
echo "<td nowrap style='font: 12px Arial; font-weight: bold'> Cell
{$i}</td>\n";
}
echo "</tr>\n";
}
echo "<tr>\n";
echo "<td bgcolor='".( ( $line % 2 ) == 0 ? '#efefef' : '#ffffff' )."'
style='font: 12px Arial;'>{$line}</td>\n";
for ( $i = 0; $i < count( $cell ); $i++ )
{
echo "<td bgcolor='".( ( $line % 2 ) ==0 ? '#efefef' : '#ffffff' )."'
style='font: 12px Arial;'>{$cell[$i]}</td>\n";
}
echo "</tr>\n";
$line++;
}
echo '<table>';

?>

All included files and required files are available in the zip file attached here.

Download Code Total Downloads: 505

Click here to Export MySQL table to CSV using PHP Code.

You might also like