Mysql update trigger change value - mysql

I have a table with a couple of columns;
datetime_end,
datetime_start,
duration
When the light is switched on, the row is inserted and only datetime_start is filled. When the light is switched off the datetime_end and duration are filled.
I want a trigger that changes the duration with 40 seconds (duration=duration-40) once the datetime_end is written.
DELIMITER //
CREATE TRIGGER trigger_light_test
BEFORE UPDATE ON light_test
FOR EACH ROW
BEGIN
IF OLD.duration > 50 THEN
SET NEW.duration = OLD.duration - 45;
END IF;
END; //
DELIMITER ;
The trigger is created just fine but doesn't do anything.. even if the light is on for 70 secs.. any ideas?

OLD contains the record from the table before the UPDATE is issued. In this case, that's NULL, so you're always comparing NULL > 50 which always evaluates to FALSE. You want to be comparing to the value in NEW, which is the value of the record as it will be, and which is the value you manipulate in the trigger.
DELIMITER //
CREATE TRIGGER trigger_light_test
BEFORE UPDATE ON light_test
FOR EACH ROW
BEGIN
IF NEW.duration > 50 THEN
SET NEW.duration = NEW.duration - 45;
END IF;
END; //
DELIMITER ;

Long time I used trigger but, if I understood your question correctly, you want the trigger to run after the update.
Wouldn't it be :
DELIMITER //
CREATE TRIGGER trigger_light_test
AFTER UPDATE ON light_test
FOR EACH ROW
BEGIN
IF OLD.duration > 50 THEN
SET NEW.duration = OLD.duration - 45;
END IF;
END; //
DELIMITER ;

Related

MySQL trigger, change value before update conditionally

I'm trying to change a value conditionally on my trigger, but I've got an error.
My trigger is:
CREATE TRIGGER `defineBase` BEFORE INSERT ON `perguntas`
FOR EACH ROW
BEGIN
IF NEW.per_base = 0 THEN
SET NEW.per_base = (SELECT per_id FROM perguntas ORDER BY per_id DESC LIMIT 1) + 1;
END IF;
END;
but doesn't work.
You need to change the delimiter to something else than ;. Otherwise the trigger definition stops at the first ;
delimiter |
CREATE TRIGGER `defineBase` BEFORE INSERT ON `perguntas`
FOR EACH ROW
BEGIN
IF NEW.per_base = 0 THEN
SET NEW.per_base = (SELECT per_id FROM perguntas ORDER BY per_id DESC LIMIT 1) + 1;
END IF;
END
|
delimiter ;
I also have the same problem. My SQL code before is just like this (without delimiter):
CREATE TRIGGER update_created_time BEFORE INSERT
ON contact FOR EACH ROW
BEGIN
SET NEW.created=NOW();
END
Then, after i add the following DELIMITER // and close it with the same //
DELIMITER //
CREATE TRIGGER update_created_time BEFORE INSERT
ON contact FOR EACH ROW
BEGIN
SET NEW.created=NOW();
END //
It works. I hope it can help someone in the future...

Update one mysql column when another is edited

I'm trying to make a datetime field that automatically gets updated with the current time only if there was a change to a certain field.
It seems I have a syntax error.
CREATE OR ALTER TRIGGER last_progress_date
ON wp_task_mgr
AFTER UPDATE
AS BEGIN
IF UPDATE (progress_percentage)
SET last_progress_date = GETDATE()
END
Just for future reference, I found the answer here:
https://dba.stackexchange.com/questions/125203/simple-trigger-to-update-two-columns-in-one-table
MySQL query:
DELIMITER //
CREATE TRIGGER trig_1 before insert
ON <table_name> FOR EACH ROW
BEGIN
IF new.due_date is not null and new.end_date='' then
set new.end_date=new.due_date;
end if;
IF new.end_date is not null and new.due_date='' then
set new.due_date=new.end_date;
end if;
END;
//
DELIMITER //
CREATE TRIGGER trig_2 before update
ON <table_name> FOR EACH ROW
BEGIN
IF new.due_date <>old.due_date then
set new.end_date=new.due_date;
end if;
IF new.end_date <> old.end_date then
set new.due_date=new.end_date;
end if;
END;
//

Loop in trigger after insert

I accidently deleted my trigger (Needed to reset something in my DB). But i don't know how to make my trigger again..
I have a 2 tables.
1:
train_information:
2:
axle:
Now, when a train gets added and inserted in the DB table: train_information. I want a trigger to also update the axle table.
After the trigger worked i want the axle table to look like:
However. If the train_information has 4 axles. i only want to put 3 in the axle table. So i want the loop/trigger to insert 1 less.
So if the train_information table has 20 axles. i want the axle table to show 19 etc.
You can have the following trigger as
delimiter //
create trigger train_information_ins after insert on train_information
for each row
begin
declare x int ;
if(new.number_of_axies > 0 ) then
set x = 1 ;
while x < new.number_of_axies do
insert into axle (train_id,axle)
values
(new.train_id,x);
set x=x+1;
end while ;
end if ;
end;//
delimiter ;
Below script will get you going. This script will loop through the number of axles which got inserted.
DELIMITER //
CREATE TRIGGER `train_information_after_insert` AFTER INSERT ON `train_information`
FOR EACH ROW
BEGIN
DECLARE noAxles INT;
SET noAxles = NEW.number_of_axles;
myLoop: LOOP
SET noAxles = noAxles - 1;
//UPDATE STATEMENT FOR AXLE TABLE HERE
IF noAxles = 0 THEN
LEAVE myLoop;
END IF;
END LOOP myLoop;
END//
DELIMITER ;

Avoid firing trigger by another trigger in MYSQL

my problem is as follows:
Table A contains list of "Tasks"
Table B contains "TaskProgress" - just an information about time spent on task, user ID, task ID and note
On table A (Tasks), I have trigger, which updates datetime of last change - column DateChanged (intended to capture datetime of edits made by user)
On table B (TaskProgress) I have trigger, which updates total time spent on a task (sum all times for given Task_ID and update column TotalTime in table A)
I wish to update DateChanged in Table A only when user mades the update (which is every time except when trigger on table B updates TotalTime)
So I wonder, whether there is a way how to tell the database not to fire TRIGGER when updating the values in another trigger.
/* set date of last change and date od closing of task */
DELIMITER $$
CREATE TRIGGER before_tasks_update
BEFORE UPDATE ON tasks
FOR EACH ROW BEGIN
SET new.DateChanged = NOW();
IF new.Status_ID = 3 THEN
SET new.DateClosed = NOW();
END IF;
END$$
DELIMITER ;
/* set total time spent on task */
DELIMITER $$
CREATE TRIGGER after_taskprogress_insert
AFTER INSERT ON taskprogress
FOR EACH ROW BEGIN
DECLARE sumtime TIME;
SET #sumtime := (SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( `timeSpent` ) ) )
FROM taskprogress WHERE Task_ID = new.Task_ID);
UPDATE `tasks` SET TimeReal = #sumtime WHERE ID = new.Task_ID;
END $$
DELIMITER ;
I use MySQL 5.5.40
Thanks, zbynek
Add a check to verify that the update implies a new TimeReal value,since only the second trigger updates that column.
DELIMITER $$
CREATE TRIGGER before_tasks_update
BEFORE UPDATE ON tasks
FOR EACH ROW BEGIN
IF new.TimeReal=old.TimeReal THEN SET new.DateChanged = NOW();
END IF;
IF new.TimeReal=old.TimeReal AND new.Status_ID = 3 THEN
SET new.DateClosed = NOW();
END IF;
END$$
DELIMITER ;

how to use trigger for restricting modification

I have used this trigger to restrict the insertion of those records for which the date of birth is less then 18. This is working fine for the new insertion, but I also want to restrict the modification of the date of birth if it is set to less then 18. Please tell how can I do this?
DELIMITER $$
CREATE TRIGGER `test_candidate_before_insert` BEFORE INSERT ON `candidate` FOR EACH ROW
BEGIN
IF
DATEDIFF(CURDATE(), NEW.date_of_birth)/365 < 18
THEN
SIGNAL SQLSTATE '12345';
END IF;
END$$
DELIMITER ;
You need to define a separate UPDATE trigger.
MySQL, unfortunately, can't create trigger "before insert or update" like other common RDBMSs.
Just create another trigger for updating:
DELIMITER $$
CREATE TRIGGER `test_candidate_before_update` BEFORE UPDATE ON `candidate` FOR EACH ROW
BEGIN
IF
DATEDIFF(CURDATE(), NEW.date_of_birth)/365 < 18
THEN
SIGNAL SQLSTATE '12345';
END IF;
END$$
DELIMITER ;