MYSQL - check a time and execute query - mysql

I'd like (if it possible) check a time and if time = special time, make update of the table.
My idea:
select current_time()
if current_time = 15:19
{
update tasks set finished = replace (finished, '1', '0')
}
Do you have any ideas???

Use an event for that
delimiter //
CREATE EVENT IF NOT EXISTS your_event
ON SCHEDULE EVERY 1 DAY
STARTS '2014-07-04 15:19:00'
ON COMPLETION PRESERVE ENABLE
DO
update tasks
set finished = replace (finished, '1', '0');
//
It will be executed automatically every day on the defined time.

Related

MYSQL drop table when all the values within a specific column are equal to "DONE"

I am programming MYSQL and I use Python on Raspberry PI 4.
I need to drop table when all the values in my status_s column are equal to "DONE". I cannot figure out how to drop table under a certain condition. MYSQL tables can be found here for testing:
https://www.db-fiddle.com/f/siZmmKWLjRDdpYX6deEPYF/1
Initially, the status_s values are not "DONE". As my program runs, the values update and eventually all of them will be "DONE", at that point, I do not want to have this table anymore as it is not important.
Thanks in advance
UPDATE Adding snippet of Python program
def update_data_when_complete(conn,table_name):
cur = conn.cursor()
sql = "SELECT COUNT(DISTINCT(ID)) = SUM(Status = 'DONE') FROM {table}"
cur.execute(sql.format(table=table_name))
complete_result = cur.fetchone()
conn.commit()
#print("COmplete result = ",complete_result[0])
# if complete_result[0] is 1 here, all rows are "DONE" and must delete table after few minutes
if(complete_result[0] == 1):
sql = "DROP TABLE {table}"
cur.execute(sql.format(table=table_name))
conn.commit()
else:
print("Table not fully complete yet")
Use Event Scheduler.
Create event procedure:
CREATE EVENT remove_temptable
ON SCHEDULE
EVERY 1 MINUTE
COMMENT 'Remove `temptable` when its `status_s` column is equal to "DONE" in all rows.'
DO
BEGIN
IF EXISTS ( SELECT NULL
FROM INFORMATOIN_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'my_database'
AND TABLE_NAME = 'temptable' ) THEN
IF !( SELECT SUM(status_s != 'DONE')
FROM my_database.temptable ) THEN
DROP TABLE my_database.temptable;
END iF;
END IF;
END;
This procedure will check the table temptable for its existence firstly. If it exists then the procedure checks does a row with non-NULL value in status_s column other than 'DONE' exists. If not then the procedure drops the table.
The procedure is executed each minute. You may adjust how often it is executed. Also, when it is created, you may enable or disable it using ALTER EVENT (for example you may enable it after temptable creation and disable after you ensure the table is dropped).
Do not forget to enable Event Scheduler.

Triggers - How to change another column when one is updated - MySQL

I have been given a use case where an user needs to update a certain TIME field if other of the same type changes.
I have been given two columns
horario_arribo (TIME)
horario_salida (TIME)
Now, what I need to do is the followin
Make a trigger so when I change for example horario_arribo, horario_salida is the same TIME as horario_arribo minus 1 hour, and the same if I update horario_salida , make horario_arribo plus 1 hour.
I have been thinking how to do it, first check if the value trying to be updated is horario_salida, then I just add 1 hour to horario_arribo, or if I'm updating horario_arribo, to the same to horario_salida but minus 1 hour.
DELIMITER //
CREATE TRIGGER modificar_horarioruta AFTER
UPDATE ON ruta
FOR EACH ROW
BEGIN
IF(new.horario_salida) THEN
SET AddTime(old.horario_arribo, '00:60:00')
ELSE
SET AddTime(old.horario_salida, Here I dont know how to minus 1 hour to that)
END IF;
END //
DELIMITER ;
This is the data I have
So , in short, if I update horario_salida, horario_arribo need to be 1 hour ahead, if I update horario_arribo, horario_salida needs to be 1 hour less.
Thanks
IIUC:
DELIMITER //
CREATE TRIGGER modificar_horarioruta AFTER
UPDATE ON ruta
FOR EACH ROW
BEGIN
IF (NEW.horario_salida) THEN
SET NEW.horario_arribo = OLD.horario_arribo + 1;
ELSE
SET NEW.horario_salida = OLD.horario_salida - 1;
END IF;
END //
DELIMITER ;
Let me know if this is not what you need.

Create trigger in mysql on insert where it compares fields of added row

I am new with mysql triggers, I have 2 tables in a database, one is called tasks and the other is task_rules.
Once a new task_rule is inserted, I want to compare the field time (which is a time object) to the current time.
if it is greater than the current time, I want to add a new row in tasks and set rid (in tasks) to id of the newly added rule, and the time field in tasks to the time field of the newly added row.
I am getting many syntax errors and i didnt know how to create this trigger.
BEGIN
DECLARE #time TIME
DECLARE #freq VARCHAR(400)
#time = NEW.time
#freq = NEW.frequency
IF (#time > NOW()) AND (#freq == 'daily') THEN
INSERT INTO task_rules ('rid', 'time') VALUES (NEW.id, #time)
END IF
END
Im doing it using phpmyadmin
1) user defined variable (those preceded with #) should not be declared see How to declare a variable in MySQL? 2) to assign a value to a variable you have to use the SET statement 3) every statement must be terminated - if you are using phpmyadmin and the default terminator is set to ; change it and terminate your statements in the trigger with ; see - https://dev.mysql.com/doc/refman/8.0/en/stored-programs-defining.html 4) null safe equals in mysql is not == from memory this should be <=> see https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html 5) you should probably set delimiters before and after the trigger 6) column names should be escaped with back ticks not single quotes. 7) for each row clause missing before begin statement.
try this
drop trigger if exists t;
delimiter $$
create trigger t after insert on task
for each row
BEGIN
DECLARE vtime TIME;
DECLARE vfreq VARCHAR(400);
set time = NEW.time;
set freq = NEW.frequency;
IF (vtime > NOW()) AND (vfreq <=> 'daily') THEN
INSERT INTO task_rules (`rid`, `time`) VALUES (NEW.id, vtime);
END IF;
END $$
delimiter ;
And do review https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html

Trigger: Referencing updated attribute

I have a Trigger on UPDATE.
What is the correct procedure for referencing attribute from the table that is not updated by the UPDATE SQL command? Is the attribute still in the UPDATE variable? I would like to get the value of that attribute for the updated row.
You can access a values of a column before update and after update in MySQL by using keywords OLD and NEW.
For example if you want to determine whether a value of a column actually has been changed during updated you can do
IF NOT OLD.column_name <=> NEW.column_name THEN
-- do something here
END IF;
Note: <=> is NULL-safe comparison operator in MySQL
BTW: There is no UPDATED virtual table in MySQL. It's from SQL Server.
Here is a SQLFiddle demo. Note that even though update affected all records in the table, only one message has been logged in log table. It's because value for a row with id 2 in the end stayed the same.
UPDATE: to keep your finished flag in sync you need triggers for all events (insert, update, delete).
DELIMITER //
CREATE TRIGGER tg_ai_event
AFTER INSERT ON event
FOR EACH ROW
BEGIN
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id = NEW.activity;
END//
CREATE TRIGGER tg_ad_event
AFTER DELETE ON event
FOR EACH ROW
BEGIN
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id = OLD.activity;
END//
CREATE TRIGGER tg_au_event
AFTER UPDATE ON event
FOR EACH ROW
BEGIN
IF NOT OLD.activity <=> NEW.activity THEN
-- if activity id was changed for an event then clculate finished flag
-- for both old and new activity id
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id IN(OLD.activity, NEW.activity);
ELSE
-- otherwise calculate finished flag only if done flag is changed
IF NOT OLD.done <=> NEW.done THEN
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id = NEW.activity;
END IF;
END IF;
END//
DELIMITER ;
Here is SQLFiddle demo

mysql stored procedure not firing from event scheduler

Can someone please tell me what's wrong with this sp. The logic seems to be ok, but when i check back in my table it doesn't work at all.
DELIMITER //
DROP PROCEDURE IF EXISTS add_zero_yearly_sales_proc //
CREATE PROCEDURE add_zero_yearly_sales_proc()
READS SQL DATA
BEGIN
DECLARE num_of_sales INT DEFAULT 0;
DECLARE last_ins_date DATETIME;
DECLARE done INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
SET last_ins_date = DATE_SUB(NOW(), INTERVAL 2 YEAR);
ins_loop: WHILE last_ins_date < NOW() DO
SELECT COUNT(sales_amount_sold) INTO num_of_sales
FROM yearly_sales
WHERE sales_date_sold BETWEEN DATE_FORMAT(last_ins_date,'%Y-%m-01 00:00:01') AND DATE_FORMAT(LAST_DAY(last_ins_date),'%Y-%m-%d 23:59:59');
IF num_of_sales = 0 THEN
INSERT INTO yearly_sales(sales_date_sold, sales_amount_sold,sales_quantity)
VALUES (CONCAT(DATE_FORMAT(last_ins_date,'%Y-%m-01 00:00:01')),0, 0);
END IF ;
SET num_of_sales = 0;
SET last_ins_date = DATE_ADD(last_ins_date, INTERVAL 1 MONTH);
END WHILE ins_loop;
SET done = 0;
END ;//
DELIMITER ;
I've created an event that fires every hour to call this procedure. The procedure is supposed to check if there are months in the yearly_sales table without any sales values in them, and if so add 0 values for the amount & quantity, and the beginning of the month for the date. I've checked back but it doesn't seem to work.
Also here's the event i created to call it hourly
DELIMITER //
CREATE
EVENT `hourly_sales_evt`
ON SCHEDULE EVERY 1 HOUR STARTS DATE_FORMAT(NOW(),'%Y-%m-%d %H:55:00')
ON COMPLETION PRESERVE
DO BEGIN
CALL add_zero_yearly_sales_proc();
END //
DELIMITER ;
May be global event scheduler is in stopped/disabled state.
To turn on event scheduler, run any of the following:
SET GLOBAL event_scheduler = ON;
SET ##global.event_scheduler = ON;
SET GLOBAL event_scheduler = 1;
SET ##global.event_scheduler = 1;
When the Event Scheduler is ON, the event scheduler thread is listed in the output of SHOW PROCESSLIST as a daemon process, and its state is represented as shown here:
mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 1
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: NULL
Info: show processlist
*************************** 2. row ***************************
Id: 2
User: event_scheduler
Host: localhost
db: NULL
Command: Daemon
Time: 3
State: Waiting for next activation
Info: NULL
2 rows in set (0.00 sec)
Once the Event Scheduler is set ON, you would see it working.
Refer to : MySQL Event Scheduler Configuration
The procedure looks OK, the logic should work. But, I want to ask you - why do you check sales_date_sold from first second -DATE_FORMAT(last_ins_date,'%Y-%m-01 00:00:01'), shouldn't it be DATE_FORMAT(last_ins_date,'%Y-%m-01 00:00:00')?
Another point: you execute SELECT statement many times in the loop, it is not effective. Try to create additional (maybe temporary table) with month numbers and join two tables to find out months without any sales. In this case you will achieve result in one step.
I'm taking a guess here without doing much digging, but I think this is your issue:
READS SQL DATA
...
INSERT INTO yearly_sales(sales_date_sold, sales_amount_sold,sales_quantity)
VALUES (CONCAT(DATE_FORMAT(last_ins_date,'%Y-%m-01 00:00:01')),0, 0);