I am trying to create a report schedule in mysql, but the query depends on the local variable fdate. How can I have mysql load the fdate variable and then run the query in the 2nd event? Thanks
CREATE EVENT fdate
ON SCHEDULE
EVERY 1 DAY
starts '2018-03-26 07:30:00'
Do
set #fdate = 2018031; #EOM prior month
create event report_1 on SCHEDULE
EVERY 1 day
starts '2018-03-26 07:31:00'
DO
<Here is the Query depending up fdate>
I think each event executes in a new session, and user-defined variables have session scope. So you can't really use those variables in events and have their value survive from one event execution to another.
Here's a test to show it:
mysql> create table log ( i int );
mysql> create event e on schedule every 1 minute do
-> insert into log set i = #a := coalesce(#a+1, 1);
If the #a variable retains its value from one event execution to the next, we'll get a series of incrementing values in my log table.
A few minutes later, we see that we don't get incrementing values. Each execution starts the counter over at 1.
mysql> select * from log;
+------+
| i |
+------+
| 1 |
| 1 |
| 1 |
+------+
But you can DECLARE a local variable, and use it in a compound statement body for an event.
CREATE EVENT fdate
ON SCHEDULE
EVERY 1 DAY
STARTS '2018-03-26 07:30:00'
DO BEGIN
DECLARE fdate INT;
SET fdate = DATE_FORMAT(LAST_DAY(CURDATE() - INTERVAL 1 MONTH), '%Y%m%d');
# following query uses fdate
END
Related
I have a log table in my Mysql database to log the events happening in my application. I want to limit the maximum number of rows in that table by deleting the old events(rows). Before deleting I want to save(backup) the old data which is going to remove to an external file. I want to run this trigger or event or whatever used to do this every 5 days or so automatically.
SET GLOBAL event_scheduler = ON;
delimiter |
CREATE event cleaner ON schedule every 7 day enable do
BEGIN
DECLARE maxtime TIMESTAMP;
DECLARE logCount integer;
SET maxtime = CURRENT_TIMESTAMP - interval 180 day;
SET logCount = (Select count(*) from eventlogs);
DELETE FROM eventlogs WHERE eventlogs.TimeStamp < maxtime AND logCount > 1000 ; END
| delimiter ;
I have a table tblMatch :
+---------+---------------------+------------------+-----------+
| ID | start_date | end_date | status |
+---------+---------------------+------------------+-----------+
| 1 | 2017-12-09 03:23 | 2017-12-10 03:23 | 1 |
+---------+---------------------+------------------+-----------+
| ... | ... | ... | 1 |
+---------+---------------------+------------------+-----------+
| 1000000 | 2017-12-22 15:12 | 2017-12-30 15:12 | 1 |
+---------+---------------------+------------------+-----------+
When I insert a row, I create one event too.
Event will change status to 0 if the match is ended.
CREATE EVENT test_event_increment_number
ON SCHEDULE AT end_date
ON COMPLETION NOT PRESERVE
DO
UPDATE tblMatch SET status = 0 WHERE ID = increment_number;
If tblMatch has 100 million matches :
Does it effect server performance?
Is it bad or good idea to create a lot of events?
Create just 1 event that runs daily and closes the matches expiring that day.
CREATE EVENT test_event
ON SCHEDULE AT 1 every day
STARTS (TIMESTAMP(CURRENT_DATE) + INTERVAL 1 DAY)
DO
UPDATE tblMatch SET status = 0 WHERE end_date = CURRENT_DATE;
UPDATE
If you want to time your events at a minute level, then either change the frequency of your event to minute level and use minute level when determining if a match needs closing, or completely drop the status field and just use the end_date field's value compared to now() to determine if the event is closed. The latter is a better way.
I Create 25 events is different time. After a while, the database takes all the resources, and reboots.
CREATE EVENT `auction_event_46709`
ON SCHEDULE EVERY 5 MINUTE STARTS '2017-12-07 10:23:03'
ON COMPLETION NOT PRESERVE ENABLE
DO CALL auction_update_price(46709)
Procedure:
CREATE PROCEDURE `auction_update_price`( IN p_id INT )
BEGIN
DECLARE cur_price INT;
DECLARE stp_price INT;
DECLARE st_price INT;
DECLARE str_price INT;
SELECT current_price, step_price, stop_price, start_price INTO cur_price, stp_price, st_price, str_price FROM product_to_auction WHERE product_id = p_id;
IF( cur_price - stp_price > st_price ) THEN
UPDATE product_to_auction SET current_price = current_price - step_price WHERE current_price > stop_price AND product_id = p_id;
ELSE
UPDATE product_to_auction SET current_price = str_price WHERE product_id = p_id;
END IF;
END
How to Fix?
Don't use events at all for this sort of operation. Certainly don't use many events for it. Instead, use a query (or view) that takes your end_date into account and determines your status value dynamically based on date. For example, to retrieve a particular item by id, do this.
SELECT id, start_date, end_date
CASE WHEN end_date <= CURDATE() THEN 0 ELSE status END AS status
FROM tblMatch
WHERE id = something
This query returns the row from the table, along with the status value based on the moment you run the query. (I set it up so items with status = 0 are always marked as expired never mind the current time.)
If you want all the items with status 1 (meaning non expired) do this:
SELECT id, start_date, end_date, 1 AS status
FROM tblMatch
WHERE end_date < CURDATE ()
AND status = 1
If you MUST use an event, you can run it once a day, sometime after midnight to reset the status columns of all expiring rows to 0, with a query like this.
UPDATE tblMatch SET status = 0 WHERE status = 1 AND end_date < CURDATE();
(I prefer to run daily update queries shortly after 03:00 local time. Why? I'm located in the USA, and our daylight saving time switchover is done, twice a year, at 02:00 local time. Doing daily updates after 03:00 ensures they'll still work properly on switchover days. )
For these queries to be efficient, you need a compound index on (status, end_date)
I am using SAILS JS and mysql adapter is being used. I have a model named as User with the following fields ID, USERNAME, EMAIL, ACTIVE_STATUS and CREATED_DATE.
By Default, active_status is set as 0. I want to update the status is 1 when created_date + 3 days is equal on Today.
Kindly suggest any possible ways to do this.
Hope you can use MySQL’s Event Scheduler
Activate it by: SET GLOBAL event_scheduler = ON;
Create event syntax:
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’
Example:
SET GLOBAL event_scheduler = ON; -- enable event scheduler.
SELECT ##event_scheduler; -- check whether event scheduler is ON/OFF
CREATE EVENT e_store_ts -- create your event
ON SCHEDULE
EVERY 24 HOURS -- run every 24 hours
DO
UPDATE myschema.users set active_status = 1
Refer: http://dev.mysql.com/doc/refman/5.5/en/create-event.html
I am writing an event scheduler in Mysql for generating tickets 3 hour prior to the user travel time. Mysl is installed in server where the server time is in UTC and 12 hour format with 5:30 hour difference with IST time. I have one user whose travel time is 7:30 in the morning, so i need to generate ticket for this user at 4:30 in the morning. I am getting current server time and converting to IST and comparing travel time and current converted time difference is 3 hours. But some how its failing and always ticket creating at 10 am in the morning. Below is my complete event writtent in Mysql,
DELIMITER $$
ALTER EVENT `Auto_Generated_Ticket` ON SCHEDULE EVERY 1 MINUTE STARTS CURRENT_TIMESTAMP ON COMPLETION PRESERVE ENABLE DO BEGIN
DECLARE UserId INT;
DECLARE v_finished INT DEFAULT 0;
DECLARE GetDate DATE DEFAULT DATE(NOW());
/*get all active user's who's tariff enddate is > today and available journeys > 0 and pass-status=4(delivered)*/
DECLARE ActiveUserId CURSOR FOR
SELECT UT.user_id FROM `um.user_trs.tariff` UT
INNER JOIN `um.user` U ON U.user_id=UT.user_id
INNER JOIN `um.user_ps.pass` UP ON UP.user_id=UT.user_id
INNER JOIN `ps.pass` P ON P.pass_id=UP.pass_id
WHERE UT.end_date >=DATE(NOW()) AND UT.available_journeys > 0 AND UT.current_balance>0 AND P.status_id=4
GROUP BY UT.user_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished=1;
SET #GetTime= DATE_FORMAT(NOW(),'%Y-%m-%d %h:%i:%s %p');
OPEN ActiveUserId;
get_userid:LOOP
FETCH ActiveUserId INTO UserId;
IF v_finished=1 THEN
LEAVE get_userid;
END IF;
SET #StartTime=(SELECT RS.start_time FROM `um.user_rm.route` UR
INNER JOIN `rm.route_schedule` RS ON RS.route_schedule_id=UR.route_schedule_id
WHERE UR.user_id=UserId
ORDER BY ABS( TIMEDIFF( RS.`start_time`, TIME(CONVERT_TZ(#GetTime,'+00:00','+05:30')) ) ) LIMIT 1);
SET #TimeDiff=(HOUR(TIMEDIFF(#StartTime,TIME(CONVERT_TZ(#GetTime,'+00:00','+05:30')))));
/*if time difference between current time and schedule start time is 3 hours then generate ticket for the user for that particular schedule*/
IF (#TimeDiff =3) THEN
/*IF (#TNumber IS NULL) THEN*/
IF NOT EXISTS(SELECT ticket_number FROM `um.user_ts.ticket` WHERE route_id=#RouteId AND route_schedule_id=#RoutScheduleId
AND user_id=UserId AND DATE(date_of_issue)=#ISTDATE) THEN
INSERT INTO `um.user_ts.ticket`
(
`user_id`,`route_id`,`route_schedule_id`,`ticket_number`,`date_of_issue`,`is_cancelled`,
`amount_charged`,`user_tariff_id`,`opening_balance`,`is_auto_generated`
)
VALUES
(
UserId,#RouteId,#RoutScheduleId,#TicketNumber,CONVERT_TZ(UTC_TIMESTAMP(),'+00:00','+05:30'),
FALSE,#PerJourneyCost,#UserTariffId,#TariffCurrentBalance,1
);
END IF;/*end of route and schedule check*/
END IF; /*end of time difference check*/
END LOOP get_userid;
CLOSE ActiveUserId;
END$$
DELIMITER ;
Please let me know if any other way to convert time or any mistake which i am not noticing in the above query.
Regards
Sangeetha
There is a dedicated mysql command to do so. CONVERT_TZ(dt,from_tz,to_tz)
See here https://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_convert-tz
From their docs:
CONVERT_TZ() converts a datetime value dt from the time zone given by
from_tz to the time zone given by to_tz and returns the resulting
value
Maybe the warning applies to you ?
Warning
Do not use a downloadable package if your system has a zoneinfo
database. Use the mysql_tzinfo_to_sql utility instead. Otherwise, you
may cause a difference in datetime handling between MySQL and other
applications on your system.
I would break it down to a minimalistic example and see if this works.
Here's how I would do it to test the basics:
Simple example:
SELECT CONVERT_TZ('2016-05-24 12:00:00','GMT','MET');
So you could build a query to determine the timediff like this:
HOUR(TIMEDIFF(
CONVERT_TZ('2016-05-24 12:00:00','GMT','MET'),
'2016-05-24 12:00:00'
))
Can anyone tell me why this event will not execute?
CREATE EVENT add_recurring
ON SCHEDULE EVERY 1 MINUTE
STARTS '2015-04-17 06:01:00'
DO INSERT INTO payment (amount, note, custID, type)
SELECT amount, note, custID, 'C' FROM recurring WHERE day = DATE_FORMAT(CURRENT_DATE(), '%e')
Here is what the recurring table looks like:
And here is the payment table which is not getting any of these values entered by the event:
Try these, assuming start date is future
try adding BEGIN , END and DELIMITER
delimiter |
CREATE EVENT add_recurring
ON SCHEDULE
EVERY 1 MINUTE
STARTS '2015-04-17 06:01:00'
DO
BEGIN
INSERT INTO payment (amount, note, custID, type), SELECT amount, note, custID, 'C' FROM recurring WHERE day = DATE_FORMAT(CURRENT_DATE(), '%e')
END |
delimiter ;
Ensure that even schedular is turned on.
SET GLOBAL event_scheduler = ON;
SET GLOBAL event_scheduler = 1;
OR in my.cnf under [mysqld] section event_scheduler=ON
I assume you have changed your system clock? The query is 2 months from now...