I'm fairly new in programming. Everything went smooth so far, but I can't solve this. I'm using MySQL Workbench 5.2.42
I know I need to create a stored procedure
This procedure needs to delete all data in my database, but only if the data I over 15 minutes old. I can access the time from my timestamp at the ExpectedEnd column. But I don't know how to do this right.
CREATE PROCEDURE p_DeleteOldData()
BEGIN
IF ExpectedEnd IS TIMESTAMP + 15
DELETE * tables FROM (DelayedLoading, Loading, LoadingDock, LoadingError, Orders, PartOrders, Semi, Trailer, Truck, Weighing)
End ;
I made this though its surely completely wrong.
edit*
I tried this, but i still can't figure how to get it to the 15 minute mark and delete.
CREATE PROCEDURE p_DeleteOldData(IN theTime DATETIME)
BEGIN
DELETE FROM Loading WHERE ExpectedEnd < theTime;
END;
Thank you in advance.
CREATE PROCEDURE p_DeleteOldData(IN theTime DATETIME)
BEGIN
DELETE FROM Loading WHERE ExpectedEnd < DATE_ADD(theTime, INTERVAL -15 MINUTE);
END;
You can see other interval values in the docs (e.g. HOUR, DAY, WEEK, MONTH) and you can even just use NOW() instead of having to pass a time value into the stored procedure if you are only looking at the current point in time
Related
I've made slight modifications to the SQL code provided in an answer to this question: How to delete a MySQL record after a certain time
However, I get a "You have an error in your SQL syntax" error each time I run the query.
create event delete_session
on schedule at current_timestamp + interval 1 day
on completion preserve
do begin
delete from session where date < DATE_SUB(NOW(), INTERVAL 7 DAYS);
end;
The code should create an event to delete entries from the session table after 7 days, but instead gives me this error. Is there actually a problem with the syntax here?
Your CREATE EVENT command and DELETE command is using the ; as delimiter. So your CREATE EVENT command is ending after the DELETE command (before END). You need to set the DELIMITER at the beginning to use another one on the CREATE EVENT command.
-- set the DELIMITER to "|"
DELIMITER |
CREATE EVENT delete_session
ON schedule AT current_timestamp + INTERVAL 1 DAY
ON COMPLETION PRESERVE
DO BEGIN
DELETE FROM session WHERE `date` < DATE_SUB(NOW(), INTERVAL 7 DAY);
END |
-- set the DELIMITER back to the default.
DELIMITER ;
... and you need to change one more thing:
remove the trailing S on DAYS.
I have a table used to store some entries with a date, which I put in a "datetime" typed field.
I'd like to automatically move those entries at that time to another table.
The result would be having a table with all the passed entries, and one with the future ones.
I was thinking about using a stored procedure, but I wouldn't know how to trigger them when I want.
Or maybe I need a standalone application always running on my server.
Or maybe I'm just not thinking to the right, banal solution...
MySQL offers events, which are like stored procedures but also run at a particular time or on a particular schedule.
The basic sequence of queries to do what you want is this.
START TRANSACTION;
SET #time := NOW() - INTERVAL 24 HOUR;
INSERT INTO archive_log
SELECT *
FROM live_log
WHERE timestamp <= #time;
DELETE FROM live_log WHERE timestamp <= #time;
COMMIT;
You'll run this as often as you need to. Each time you run it you'll move old records from the live_log table to the archive_log table. The phrase - INTERVAL 24 HOUR governs how old the records must be to move them.
You can run this as a MySQL event. For this to work event scheduling must be on in your MySQL server. Read this. https://dev.mysql.com/doc/refman/5.6/en/events-configuration.html
Here's how you declare this event.
CREATE EVENT `archiver`
ON SCHEDULE EVERY 4 HOUR
STARTS '2015-05-23 15:11:23'
ON COMPLETION PRESERVE DO
BEGIN
START TRANSACTION;
SET #time := NOW() - INTERVAL 24 HOUR;
INSERT INTO archive_log
SELECT *
FROM live_log
WHERE timestamp <= #time;
DELETE FROM live_log WHERE timestamp <= #time;
COMMIT;
END
Notice that the query is embedded in the CREATE EVENT code. Debug the query first, before you put it into the event, because debugging events is hard.
I must have done something really stupid, but the following is correct:
CREATE EVENT delete_old
ON SCHEDULE
EVERY 1 DAY
COMMENT 'Clears old cache data from the DB.'
DO
DELETE FROM summoners
WHERE `date` < (NOW() - INTERVAL 7 DAY);
Where the next bit seems to throw a syntax error on the last 2 lines:
CREATE EVENT delete_old
ON SCHEDULE
EVERY 1 DAY
COMMENT 'Clears old cache data from the DB.'
DO BEGIN
DELETE FROM summoners
WHERE `date` < (NOW() - INTERVAL 7 DAY);
END;
The syntax to my knowledge is correct, however MySQL Workbench does not agree. I intend to do multiple tables inside the BEGIN - END section, that is why i need it.
I hope someone can figure out what goes wrong here, i am at a loss.
Thanks in advance,
Smiley
You have to change the DELIMITER to something that doesn't appear in your event body.
I just tried it (MySQL Workbench 6.0.6, MySQL 5.6) and it works fine. Here's a screenshot:
It's because ; in body breaks your command in the middle. Use different delimiter.
DELIMITER |
CREATE EVENT delete_old
ON SCHEDULE
EVERY 1 DAY
COMMENT 'Clears old cache data from the DB.'
DO BEGIN
DELETE FROM summoners
WHERE `date` < (NOW() - INTERVAL 7 DAY);
END;
| DELIMITER ;
I want to delete some messages from my MySQL database after 7 days.
My message table rows have this format:
id | message | date
The date is a timestamp in the normal format; 2012-12-29 17:14:53
I was thinking that an MySQL event would be the way to go instead of a cron job.
I have what I guess is a simple question to an experienced SQL person, how do I code the delete messages portion in brackets below?
An example would be appreciated, Thanks.
DELIMITER $$
CREATE EVENT delete_event
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
ON COMPLETION PRESERVE
DO
BEGIN
DELETE messages WHERE date >= (the current date - 7 days);
END;
$$;
You can try using this condition:
WHERE date < DATE_SUB(NOW(), INTERVAL 7 DAY)
So that the whole SQL script looks like this:
CREATE EVENT delete_event
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
ON COMPLETION PRESERVE
DO BEGIN
DELETE messages WHERE date < DATE_SUB(NOW(), INTERVAL 7 DAY);
END;
However, on your place I would solve the given problem with a simple cron script. The reasons to do this is simple: it's easier to maintain the code, no ugly SQL workarounds, integrates smoothly with your system.
This should do the trick.
DELETE FROM messages WHERE date < (CURDATE() - INTERVAL 7 DAY);
For those out there who are on a shared hosting, like 1and1's, and can't create events, an alternative is to use webcron
You just need to tell webcron the url of the php script you'd like to be run, and they'll trigger it for you at the intervals you want
This returns 1 (aka TRUE)
SELECT DATE_SUB(NOW(), INTERVAL 24*100 HOUR) = DATE_SUB(NOW(), INTERVAL 100 DAY);
100 days ago, the hour of day does not change. But due to Daylight Savings Time (US), 100 twenty-four hour periods ago is actually one hour earlier than if you counted by days. If the above statement accounted for DST, it would return 0 or FALSE.
Is there a way I can say to account for DST for a given statement or session? I would prefer not to use UNIX_TIMESTAMP since it cuts off anything past 2038.
You'll need to create a custom function, something like this.
DELIMITER $$
CREATE FUNCTION DST(ADatetime DATETIME) RETURNS DATETIME
BEGIN
DECLARE result DATETIME;
SET Result = ADatetime;
IF ADatetime >= startDST AND ADateTime <= endDST THEN
result = DATE_SUB(ADatetime, INTERVAL 1 HOUR);
END IF;
RETURN result;
END $$
DELIMITER ;
This is really just a matter of converting to UTC and back:
CONVERT_TZ(DATE_SUB(CONVERT_TZ(NOW(),##session.time_zone,'UTC'), INTERVAL 24*100 HOUR),'UTC',##session.time_zone);
This assumes you have the timezone tables set up to use named time zones. If not, you can use '+0:00' instead of 'UTC'
How would cutting off anything past 2038 be a real problem when you can be sure that 64bit integer timestamps will be immplemented everywhere 20 years before that at least ?
Seriously, there are so many issues with the datetime / timestamp types in MySQL that you should try and avoid them when possible.
Do you store many dates beyond 2038 ?
And, why not try using PostgreSQL which has much more advanced type support ?