Trigger Error , MySQL - mysql

Well, I have researched and have not found a solution to the following problem 'SQL Error (1442): Can not update table' messages' in stored function / trigger because it is already used by statement Which invoked this stored function / trigger. `
My trigger is created, only when I run the INSERT on the table of messages, this error is thrown, my trigger is
DELIMITER $$
DROP TRIGGER IF EXISTS `onMessage` ;
CREATE TRIGGER `onMessage` BEFORE INSERT ON `messages` FOR EACH ROW
BEGIN
UPDATE `users` SET `users`.`messages` = ( `users`.`messages` + 1 )
WHERE `users`.`uid` = NEW.uid ;
DELETE FROM `messages` WHERE `date` < ( NOW( ) - INTERVAL 1 MINUTE ) ;
END ;
$$
DELIMITER ;

This is a restriction in the use of triggers.
From the MySql documentations:
Within a stored function or trigger, it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.

Correct, for MySQL anyway
You can't write to the table associated with a trigger in that trigger. It generates all manner of inconsistencies, not least because MySQL triggers are processed row-by-row (RBAR)
In this case, I'd use a stored procedure to deal with the INSERT on messages

It is not possible to update a table for which the trigger is created in the trigger since Mysql does some locking stuff on that table. Therefore you can't insert/update/delete rows of the same table because then the trigger would called again and again, ending up in a recursion.
If you want to create a trigger on the table which will update itself (perfoming a deletion in this case), make sure you use the NEW.column_name to refer to the row after it’s updated.

Related

Mysql can't update rows when my trigger is called

My trigger fails when i try to insert a new row in my table because Mysql doesn't support updating rows in the same table the trigger is assigned to. Does anyone have suggestions on a good workaround/alternative?
My trigger:
-- Trigger DDL Statements
DELIMITER $$
CREATE TRIGGER check_sequence
BEFORE INSERT ON data FOR EACH ROW
BEGIN
IF EXISTS(SELECT TRUE FROM data WHERE sequence = NEW.sequence) THEN
UPDATE data SET sequence=sequence+1 WHERE sequence >= NEW.sequence;
END IF;
END $$
DELIMITER ;
Error Sql that is displayed when i try to insert new row:
ERROR 1442 (HY000): Can't update table 'data' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Thanks for answer,
In MySQL, You can't update (or insert in) table A in a trigger for table A.
http://dev.mysql.com/doc/refman/5.0/en/stored-program-restrictions.html
You can try a sproc and use a transaction, or consider PostgreSQL, which can do this.

Mysql triggers Create error

This is my create triggers . I want when Insert vhftofass it execute this query(UPDATE vhf_msg_rx SET msg_text="";) that means Its make Null this table vhf_msg_rx.But when i write that query after insert Query it make error (Can't update table 'vhf_msg_rx' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.) Please help me how can i do this
CREATE
/*!50017 DEFINER = 'root'#'localhost' */
TRIGGER `VHFtoFASS` AFTER UPDATE ON `vhf_msg_rx`
FOR EACH ROW BEGIN
INSERT INTO vhftofass SELECT NULL,msg_text,NOW(),0 FROM vhf_msg_rx WHERE msg_text<>"";
END;
$$
I'm not completely clear on what you're trying to do, but it seems like you want to copy modified rows of one table into another, but only retaining certain fields. You could do that by referencing the inserted record with NEW.columnname inside the FOR EACH ROW loop, for example
CREATE TRIGGER `VHFtoFASS` AFTER UPDATE ON `vhf_msg_rx`
FOR EACH ROW BEGIN
INSERT INTO vhftofass VALUES(NULL,NEW.msg_text,NOW(), 0);
END;
Note that this will only handle updates - you'll need an INSERT trigger to capture new rows.

Setting up a trigger in PHPMyAdmin

I'm trying to comprehend triggers, and I think I fully understand them, but I haven't been able to implement any of them. I want this code to delete a user with the name "test". So if anyone updates their name to "test" the user should be deleted.
My example code:
CREATE TRIGGER `my_trigger`
BEFORE UPDATE ON `my_db` FOR EACH ROW
BEGIN
DELETE FROM my_table WHERE `username` = 'test';
END
My error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 4
I can't figure out why the delete statement is giving me an error. Any ideas?
Here is the syntaxically correct SQL:
DELIMITER ;
DROP TRIGGER IF EXISTS `my_trigger`;
DELIMITER $$
CREATE TRIGGER `my_trigger`
BEFORE UPDATE ON `my_table` FOR EACH ROW
BEGIN
DELETE FROM my_table WHERE `username` = 'test';
END$$
DELIMITER;
But it won't work, because you can't delete from the table, you are updating:
A trigger can access both old and new data in its own table. A trigger
can also affect other tables, but it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
http://dev.mysql.com/doc/refman/5.5/en/faqs-triggers.html#qandaitem-B-5-1-9
If you want a simple example, try this:
DELIMITER ;
DROP TRIGGER IF EXISTS `my_trigger`;
DELIMITER $$
CREATE TRIGGER `my_trigger`
BEFORE UPDATE ON `my_table` FOR EACH ROW
BEGIN
SET NEW.`username` = 'aaa';
END$$
DELIMITER;
This will always set 'aaa' as the user name when updating.
It's possible to associated trigger only with a table.
Also within a stored function or trigger, it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
Restrictions on Stored Programs

Updating DATETIME with trigger, get error 1442 in MySQL

I am having trouble with a trigger in MySQL. I have a column named "last_modified" that I want to be automatically updated with the current date and time when it is the table is edited. Using a trigger, this is my SQL query:
delimiter //
CREATE TRIGGER trg_update_responders BEFORE UPDATE ON survey_responders
FOR EACH ROW
BEGIN
UPDATE survey_responders
SET NEW.last_modified = CURRENT_DATETIME();
END;//
However, when I update the table, such as with this query:
UPDATE survey_responders SET first_name = "bob" WHERE id = "1";
MySQL Workbench displays error 1442: "Can't update table 'table_name' in stored function/trigger because it is already used by statement which invoked this stored function/trigger"
I have looked at similar questions with the same error but still have not fixed it. Help is appreciated.
** UPDATE **
This did the trick:
delimiter //
CREATE TRIGGER trg_update_responders BEFORE UPDATE ON survey_responders
FOR EACH ROW
BEGIN
SET NEW.last_modified = CURRENT_TIMESTAMP();
END;//
Seems like I simply did not need to repeat the
UPDATE survey_responders
and CURRENT_DATETIME() did not exist, I had to use CURRENT_TIMESTAMP().
This did the trick:
delimiter //
CREATE TRIGGER trg_update_responders BEFORE UPDATE ON survey_responders
FOR EACH ROW
BEGIN
SET NEW.last_modified = CURRENT_TIMESTAMP();
END;//
Seems like I simply did not need to repeat the
UPDATE survey_responders
and CURRENT_DATETIME() did not exist, I had to use CURRENT_TIMESTAMP().
What you are trying to do is not possible using a trigger.
Within a stored function or trigger, it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
Source
You need to do this some other way.
See here: MySQL - Trigger for updating same table after insert
The typical way to do that, is to create a stored procedure, that
inserts into/Updates the target table, then updates the other row(s),
all in a transaction.

mysql trigger - is there anything like FOR EACH TABLE

MySql trigger is very interesting, but very tricky.
I have some problem, I want to run a trigger once after insert on .
I want to run my trigger once after rows inserted, is there anything like for each table``???
how to make this trigger run only once, but not for each row created.
CREATE
DEFINER=`root`#`localhost`
TRIGGER `mydb`.`leave_taken_trigger`
AFTER INSERT ON `mydb`.`leave`
FOR EACH ROW
BEGIN
set #lt:= (SELECT count(*) FROM `leave` where (staff_leave_application_staff_id_staff = new.staff_leave_application_staff_id_staff and leave_type_id_leave_type = new.leave_type_id_leave_type) and active = 1 );
INSERT INTO `leave_taken`(leave_type_id_leave_type, staff_id_staff, taken_days, updated)
VALUES (new.leave_type_id_leave_type, new.staff_leave_application_staff_id_staff, IFNULL(#lt,0), CURDATE())
ON DUPLICATE KEY UPDATE taken_days=IFNULL(#lt,0), updated = CURDATE();
END$$
I think you can't achieve your requirement with trigger.
Your trigger will run in every row created.
I suggest you to using stored procedure from your code after the INSERT has successfully completed.