Schedule Event in MySQL - mysql

I have been trying to find this answer for quite some time with no avail. Here is what I have to do. I create the very first record in the table below. Then I would like to schedule an event that is recurrent once a week to insert a new record into this table. All I need is this event to do is add a week from the field of the last row in the table once a week.
preferred output (something like this)
+----+------------+------------+
| id | start | end |
+----+------------+------------+
| 1 | 2014-12-04 | 2014-12-11 | <-- Manually Inputed (base dates)
| 2 | 2014-12-11 | 2014-12-18 | <-- SQL Scheduled Events below
| 3 | 2014-12-18 | 2014-12-25 | (Every Thursday :D)
| 4 | 2014-12-25 | 2015-01-01 |
+----+------------+------------+
SQL statement so far
INSERT INTO `publication_dates` (`id`, `Start`, `End`) VALUES (null,"2014-12-04", DATE_ADD("2014-12-04",INTERVAL +1 WEEK));
I haven't created an event for this because I have literally no idea how to get the information from the row before it. This will help me get over the hurdle I've hit in my laravel project.
Thank you for your time in advance!
MySQL Systax Error for
DELIMITER &&
CREATE EVENT new_publication
ON SCHEDULE EVERY 1 WEEK STARTS '2014-12-04 00:00:00'
DO BEGIN
INSERT INTO publication_dates (`Start`, `End`)
VALUES (NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY));
END &&

You can achieve this using the mysql event scheduler if you let the first row to be created by the event as well.
Start the event on the first date that you want to enter. And the event should run the insert query below.
INSERT INTO publication_dates (`start`, `end`)
VALUES (NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY));
For events to work, you need to launch the mysql instance with event scheduler on or you can turn it on by running this query:
SET GLOBAL event_scheduler = ON;
Then you have to create an event that will run every Thursday, say at midnight.
DELIMITER &&
CREATE EVENT run_on_thursdays
ON SCHEDULE EVERY 1 WEEK STARTS <starting thursday> ENDS <ending thursday>
do begin
<the insert query from above>
END &&
This will enter the first value on the and keep adding a row every Thursday until the ending Thursday.

Related

how to execute a trigger everyday at once in sql

we are doing a project on microbanking and we need to calculate the interest rate in database level. So we used procedures and triggers for that. but the trigger needs to execute everyday at once to perform below given procedure. Can you provide a solution to create that trigger. Thanks in advance
DELIMITER //
create procedure addFDInterestToAccount(in account_number bigint(20))
BEGIN
declare interest float default 0;
declare account_type varchar(10);
declare rate float;
declare savings_account bigint(20);
start transaction;
select balance from fd_account where account_no = account_number into interest;
SELECT plan_id from fd_account where account_no = account_number into account_type;
SELECT saving_account_no from fd_account where account_no = account_number into savings_account;
select interest_rate from fd_plan where plan_id = account_type into rate;
set interest = interest*rate/1200;
insert into transaction (transaction_id, account_no, credit_debit, date_time, amount, type_, agent_id, is_fee) values (null, savings_account, 'debit', now(), interest, 'not_special', null, false);
update account set balance = balance + interest where account_no = savings_account;
commit;
END //
DELIMITER ;
call addFDInterestToAccount(90842311);
As far as I understood your requirement, I think you can use SQL Events for this. The general syntax goes like this,
CREATE [OR REPLACE]
[DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO sql_statement;
schedule:
AT timestamp [+ INTERVAL interval] ...
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...]
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
You can modify/use following code for achiving this,
CREATE EVENT example
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP
DO call addFDInterestToAccount(90842311);
For further information you can vist the link here
Also make sure you run this query before running the event
SET GLOBAL event_scheduler = ON;
A trigger is defined as a procedure that runs in response to an insert, update, or delete statement. It will run every time you perform one of those DML operations. You cannot schedule a trigger to run once a day.
From the MySql documentation (but applicable to all databases that implement triggers):
A trigger is defined to activate when a statement inserts, updates, or
deletes rows in the associated table. These row operations are trigger
events.
Instead, you need to look for a task scheduler. Each OS will have its own or you could find a third-party scheduler software.

MySQL select records from last month or before

I want to run a CRON job at the beginning of every month to select all the records that are from the last month or even prior to that. The script runs at ~00:15am on the first of the month but the SELECT must not include records that may have been created within that ~15 mins. The column I'm running the condition against is stored as datetime and the database is MySQL.
EDIT:
Example:
rowID | time
---------------------------
6 | 2016-06-01 00:12:21
5 | 2016-06-01 00:04:34
4 | 2016-05-28 19:46:45
3 | 2016-05-17 19:25:01
2 | 2016-05-08 06:33:32
1 | 2016-04-25 12:22:54
Basically, looking for all rows where ID < 5.
SELECT rowID
FROM table
WHERE time < beginning_of_current_month;
Thanks in advance!
Have you tried something like this?
select rowID from table
where time < DATE_FORMAT(NOW(), '%Y-%m-01')

MySQL Event Insert ID from another table

I would like to create an event that when a lend_date column has passed exactly 15 days, it would execute an INSERT query.
It would get the ID of that row and userid, and insert it to another table.
For example:
id | userid | lend_date
---+----------+----------------------
1 | 1 | 2015-09-24 15:58:48
2 | 1 | 2015-09-21 08:22:48
And right now, it is exactly 2015-10-06 08:23:41. So the event should get the ID of the second row, which is 2, and insert it to another table.
What should my event query look like?
The event type is RECURRING. But I'm also not sure if I should execute it every hour or everyday. What would be the best recommendation for it?
And is this a better way than using Task Scheduler?
The other table that I wanted to insert the fetched ID is notification_table, where it will notify the user that he/she has an overdue date.
notification_table looks like this:
id | userid | notificationid | notificationdate |
---+----------+------------------+----------------------+
1 | 1 | 1 | 2015-09-24 15:58:48 |
2 | 1 | 1 | 2015-09-21 08:22:48 |
I'm looking at this query:
INSERT INTO notification_table (id, userid, notificationid, notificationdate)
SELECT id, userid, 1, NOW()
FROM first_table
WHERE lend_date + INTERVAL 15 DAY = NOW();
Seeing the words exactly, event, and datetime in the same sentence makes me cringe. Why? For one thing, it's hard to get one datetime value to exactly match another. For another thing, events often run slightly after the scheduled time, especially on a busy database server. It takes them a little time to start up.
If you need the id values from a table where the records are more than 15 days old, the most time-precise way to get them is with a query or view.
CREATE OR REPLACE VIEW fifteen
AS SELECT id
FROM table
WHERE `datetime` < NOW() - INTERVAL 15 DAY
You can, of course, write an event to copy the ids to a new table. You'll have to go to some trouble to make sure you don't hit the same id values more than once, by using this sort of query in the event.
INSERT INTO newtable (id)
SELECT id
FROM table
WHERE `datetime` < NOW() - INTERVAL 15 DAY
AND id NOT IN (SELECT id FROM newtable)
How often should you run the repeating event? That depends entirely on how quickly the id values need to make it into the new table after they turn fifteen days old. If your application requires it to be less than a minute, you really should go with the view rather than the event. Anything more than a minute of allowable delay will let you use a repeating event at that frequency.

mysql - Compare current timestamp against two time ranges

I have a database which holds information about daily functions' opening times.
Usually, the database only has the function ID and the opening times, but here I have the function name as an example.
Table: opening_times
| function_id | function_name | day_open | day_close | eve_open | eve_close |
|-------------|------------------|------------|------------|------------|------------|
| 1 | Charity Function | 1357027200 | 1357056000 | 1357063200 | 1357081200 |
I'd like to write an SQL statement, which sees whether the function has:
Not yet opened for day
Daytime Open
Lunch Break
Evening Open
Closed for day
This will obviously have to compare the current time[stamp] against the two date ranges I have stored in the database.
Could someone help me to achieve this. Once I have the syntax, I will learn!
I can do a standard IF statement, to see whether this is between ONE time-range, but this obviously doesn't achieve the result I need:
Thanks!
Try this::
SELECT
CASE IF UNIX_TIMESTAMP() BETWEEN ot.`day_open` AND ot.`day_close`
THEN 'Within daytime open range'
ELSE 'Not in daytime open range' END as open_status
FROM opening_times ot
SELECT
CASE
WHEN UNIX_TIMESTAMP( ) < ot.`day_open`
THEN 'Function has not started'
WHEN UNIX_TIMESTAMP() BETWEEN ot.`day_open` AND ot.`day_close`
THEN 'function open'
WHEN UNIX_TIMESTAMP() BETWEEN ot.`day_close` AND ot.`eve_open`
THEN 'Mid-Day Break'
WHEN UNIX_TIMESTAMP() BETWEEN ot.`eve_open` AND ot.`eve_close`
THEN 'Evening Open'
WHEN UNIX_TIMESTAMP() > ot.`eve_close`
THEN 'Closed for day'
END AS function_open_status
FROM opening_times ot WHERE ot.function_id=1

Move rows from TableA into Table-Archive

Is it possible to move rows that are 3 days old into an other table called "Table_Archive" automatically in mysql ones a week?
tableA ex:
ID | stringvalue | Timestamp
1 | abc | 2011-10-01
2 | abc2 | 2011-10-02
3 | abc3 | 2011-10-05
4 | abc4 | 2011-10-10
5 | abc5 | 2011-10-11
After the move
tableA:
ID | stringvalue | Timestamp
4 | abc4 | 2011-10-10
5 | abc5 | 2011-10-11
Table_Archive:
ID | stringvalue | Timestamp
1 | abc | 2011-10-01
2 | abc2 | 2011-10-02
3 | abc3 | 2011-10-05
And when new input comes into tableA it wont be any problems with ID (PK) in the next move?
What Ive got:
CREATE PROCEDURE clean_tables ()
BEGIN
BEGIN TRANSACTION;
DECLARE _now DATETIME;
SET _now := NOW();
INSERT
INTO Table_Archive
SELECT *
FROM TableA
WHERE timestamp < _now - 3;
FOR UPDATE;
DELETE
FROM TableA
WHERE timestamp < _now - 3;
COMMIT;
END
How do I change _now to be the date 3 days ago?
Personally, I would make use of the MySQL Event Scheduler. This is a built in event scheduler rather like CRON in Linux.
You can specify it to call a procedure, procedures or functions or run a bit of SQL at designated intervals.
Read the MySQL docs but an example would be:
CREATE EVENT mydatabase.myevent
ON SCHEDULE EVERY 1 WEEK STARTS CURRENT_TIMESTAMP + INTERVAL 10 MINUTE
DO
call clean_tables();
So this is saying "call clean_tables() once a week and make the first call in 10 minutes' time"
One gotcha is that the event scheduler is (I think) disabled by default. To turn it on run:
SET GLOBAL event_scheduler = ON;
You can then run:
SHOW PROCESSLIST;
To see whether the event scheduler thread is running.
As for preserving your Table A ID column (if you must). I would keep the ID on Table_Archive as unique to that table i.e make it the primary key & auto_increment and then have a 'Original_TableA_ID' column in which to store the TableA ID. You can put a unique index on this if you want.
So Table_Archive would be like:
create table `Table_Archive` (
ID int unsigned primary key auto_increment, -- < primary key auto increment
tableAId unsigned int not null, -- < id column from TableA
stringValue varchar(100),
timestamp datetime,
UNIQUE KEY `archiveUidx1` (`tableAId`) -- < maintain uniqueness of TableA.ID column in Archive table
);
Nobody seems to have answered your original question "How do I change _now to be the date 3 days ago?". You do that using INTERVAL:
DELIMITER $
CREATE PROCEDURE clean_tables ()
BEGIN
BEGIN TRANSACTION;
DECLARE _now DATETIME;
SET _now := NOW();
INSERT
INTO Table_Archive
SELECT *
FROM TableA
WHERE timestamp < _now - interval 3 day;
FOR UPDATE;
DELETE
FROM TableA
WHERE timestamp < _now - interval 3 day;
COMMIT;
END$
DELIMITER ;
One final point is that you should consider creating an index on the timestamp column on TableA to improve the performance of you clean_tables() procedure.
You may need to have a look into cron jobs if you want that script/query to be executed automatically.
If you are using cpanel have a look into http://www.siteground.com/tutorials/cpanel/cron_jobs.htm
Adding to the best answer (imo) by Tom Mac regarding the event scheduler - be aware that when backing up the schema, you have to specify that you want the events backed up with it via the --events=TRUE flag.
If you're exporting manually in the workbench, the latest version has a checkbox on the main 'Export To Disk' tab - older versions hide it away in the Advanced Export Options tab.
It is possible, MySQL will execute query automatically at specific time using MySQL Event Scheduler. Check this link for more details.
https://dev.mysql.com/doc/refman/5.7/en/event-scheduler.html