How to schedule an event in Mysql on table update? - mysql

I want to initiate an action after 7 days from the day a specific field in my database table is updated.
I can use trigger to trigger an event on update of field in the database table. But how can I make it wait for 7 days. I was looking for scheduling an Event but that can only be scheduled for specific time. Is there any way to dynamically set the schedule time?

There are 2 ways to do it:
You store in a timestamp field when the record was last updated. You schedule a regular event to be run every couple of hours. The event's code scans the table in question and does whatever needs to be done for those records those timestamp is between the lust run of the even and the current time.
If you have lots of records you need to handle such events, then this is the recommended approach. The drawback is that timing of the event may not be fully accurate, depending on how often you schedule this event to run.
Every time you update the record you create an event specifically for that record in a trigger or stored procedure that triggers in 7 days time.
This approach gives you absolute accuracy over when an event is triggered, however, if you have a large number of changes, then this solution does not scale well.
An alternative solution could be to record the time when the change was done, but instead of event triggering base your code on user interaction. So, if the user, whose data has been updated logs on then you notify him about what you want regarding those updates that were done more than 7 days ago and the events were not seen by the user.

Related

MySQL Calendar recurrent events with custom information

I am creating a booking management system in which it is allowed to create recurrent events.
Searching around, I understood that creating "repeating patters" would be an optimal idea for the DB design, as explained here: Calendar Recurring/Repeating Events - Best Storage Method
My issue comes from the fact that I would need to add some data for each single event, such as if payments have been made for each single event, confirmation, notes, etc.
This would end in creating a different table with a single row for each event created. In other words, physically adding a row for each event instead of using "recurrent patterns".
I can't see a solution for avoiding 1 line in the DB for 1 event. Any suggestion? In my system, each user would not have many events, let's say a maximum of 50 events per week.
Let's assume you have a table already to store recurrent events, such as
table recurrent_event
id bigint
start date
interval int -- as simple or complex as needed
Now your application will need some logic anyway to calculate which single events will come from this, e.g. to display a list of single events. I would not store a list of all these singles events in the database, as, initially, this list wouldn't add any useful information. Also, the list would have to end somewhere, so it might fail to encompass all single events coming from the recurrent event. The only need to insert a record for a single event arises when some additional information for the event gets actually entered. Just for these single events, I'd create a
table single_event_additional_info
id bigint
recurrent_event_id bigint
single_event_date date
additional-information ... whatever datatype fitting
that points back to the recurring event. So, when treating a recurring event, selecting from this table all single events referring to it will yield all information relevant for the recurring event. The rest of single events will still be determined by calculation.

Delete Row at Set Time

I'm creating a database table where rows need to be removed after a set time. That time is defined in minutes by the valid_time cell in that row. I found this answer though I am not sure how I can implement what I need to into it.
Is someone able to tell me how I can implement this time (as minutes) into the event in the previous answer or if it's not possible, another way to do so. Thanks.
Clarification, I have two columns in the table. One is created which is a TIMESTAMP of when the row is created, and the second is valid_time, an integer in minutes of how long the row is valid for.
DELETE FROM table WHERE created < DATE_SUB(NOW(), INTERVAL `valid_time` MINUTE)
You can try to use the MySQL event scheduler and attach a DELETE query to it. That DELETE will be a simple query that will delete all records where current_time is greater that the valid_time/valid_until fields.
You can configure the scheduler to run in a minute/hourly/daily/... basis as you wish to erase the registers.
Check here and here for more information. M0rtiis offered the query example.

Observe age of entries in the database and trigger event

I'm wondering if there's a way to trigger an event into a database based on the age of the row entry. Based in a datetime field I will need to retrieve the entrys that match an exact age, but I don't want to stress the database. So I need the database to create an event in where if the field is in the database when the time comes, it will send a message or something like that.
Examples:
I have an entry that was created 23:59 hours ago. I want to trigger an event when the field reaches 24:00 hours.
I have a backend which should receive a command each time an entry becomes 1 day old.
When you INSERT the row (or otherwise set/change the time), create a one-time EVENT for 24 hours hence.
This would have to be in your application code, since "Events cannot be created, dropped or altered by another stored program, trigger or event."

How to combine a trigger and an event and have the event use a specific row id?

I have the following problem to solve. I need rows inserted into a "reservations" table to, upon insertion, set a timer for themselves and then check a flag within this newly created row some minutes later to see if it has changed from "pending" to "completed" (which would be caused by user action in the intervening period) and if still "pending" to remove themselves from the table.
The idea here is that people are making reservations and the act of beginning the reservations process adds this row, however, if they fail to complete the purchase over a period of time I want to remove the rows to make the reservations (of which there is a finite amount) available to other consumers.
So, I've been looking at events and triggers and I get the concept for both, but what I'm failing to find is a way for the trigger to pass *this row's id to the event so that when the event fires it only looks at the relevant row because I don't want it to notice *all the rows that might be "pending" since there may have been newly created "pending" rows by other consumers for other reservations in the intervening period, and I obviously don't want to mess with those until their respective timers have elapsed.
So... what I am hoping for (in pseudo) is...
/*EVENT*/
CREATE EVENT IF NOT EXISTS delete_abandoned_pending_purchase
ON SCHEDULE AT CURRENT_TIMESTAMP + 5 minutes
DO
delete from tickets where state = 'PENDING' and id = [MY ROW ID]
and then...
/*trigger*/
CREATE TRIGGER remove_if_unused
AFTER INSERT ON `tickets` FOR EACH ROW
begin
[call delete_abandoned_pending_purchase with row_id MY_NEW_ROW_ID]
end
I'm guessing maybe I need to make a stored procedure that takes a parameter and then pass that row ID as the param? Or perhaps there's a more straight forward way... I'm just failing to find the syntax for this and would love some guidance. Obviously I can handle this in the business logic that wraps this data interaction, but felt that this was a more elegant approach.
[EDIT]
reading more about this
"There is no way to pass parameters directly to or from events; however, it is possible to invoke a stored routine with parameters within an event".
But the suggestion there is to call a stored procedure and pass it a param. However, my problem is that I don't see how to get *at the row.id in the event to pass to the stored proc. I feel like I must be missing something obvious... how can events not have access to specific row ids?
[EDIT EDIT]
so, based this I'm sensing that this is actually not doable in mySQL... that's a bummer and also quite surprising. Seems like a really obvious thing to want to do.
I'll leave the question open and see if anyone chimes in with a clever alternative.
I would recommend you do this via a script, less complexity and more control. Something like below:
MaxSleep=300 # In seconds SleepTime=MaxSleep
while (1) {
sleep SleepTime; delete from TheTable where reserved = 'pending' and the_timestamp >= Current_Timestamp; SleepTime='mysql
'select the_timestamp from TheTable where reserved = 'pending' order
by the_timestamp limit 1"
if SleepTime is null then SleepTime= MaxSleep
}
You could just do an event that checks against the whole table, should be fast if it is indexed correctly and then the business logic is in the DB. Perhaps use a minute as the check then max pending transaction is 6 Minutes if you have a 5 minute timeout.
CREATE EVENT delete_abandoned_pending_purchase
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 Minutes
DO
BEGIN
delete from TheTable where reserved = 'pending' and the_timestamp >= Current_Timestamp;
END

How to calculate the difference between times and store the result in a mySQL database (VB.NET)?

I'm quite new to VB and i'm working on a project to record the details of employees clocking in and clocking out. I want to know how to make it so when the 'clock in' button is clicked the time will start recording and when the 'clock out' button is pressed the time will stop recording. Also once clock out is clicked the hours in between clock in and clock out will be recorded and stored into a mySQL database.
This information will be outputted onto a DataGrid showing the time and date of when the employee has clocked in.
Then the amount of hours will be multiplied by a pre-written hourly wage .. which is already stored inside one of the tables in my mySQL database.
Any help would be appreciated.
You should store the event instead of the result.
Store the clock-in time as well as a row for the clock-out time.
Then you will need a procedure either on your database or in the application that will iterate over the rows and match clock-ins to clock-outs.
This approach will let the application crash/terminate and restart without losing data.
Alternatively you could put the clock-in and out in the same record (different columns), and just insert the clock-out into the first row that matched employee and null clock-out.
I would have the clock In button fire an event in the program that created a record for the employee ID I'm assuming you have at that time.
Then once the clock out button is clicked you would fire an event that would go out to your database and pull in the first record it found with the employee ID you are looking for, a valid clock in time and a null for the clock out time. If the program didn't find something that matched all that criteria you would have to handle that however you wanted (I would do the lookup when the employee logged in or whatever and only allow them access to the clock in button if there was no record present and only allow them to use the clock out button if there was a record found for their ID).
Once you have that record in memory you should set the clock out time and calculate the difference using the clock in time that was written to the database earlier.
I would use a stored procedure in the database to handle adding/updating/managing the record and do all the calculations and whatever else you want to do at the time of the clock in/out inside the program itself. But I think its all just preference as far as where the actual processing takes place is concerned.
The most obvious reason for this is that the program can be shut down in between clock in's and clock out's without losing anything at all. If you try to keep track of it all in memory you will lose all your clock in's once the program is shut down for whatever reason(closed manually/"End Task"ed through task manager/unhandled error).