I have an application, which cannot update rows, only insert them, but If something is already inserted into the database and it tries to insert a row, it generates a duplicate key error.
I tried to create a trigger for the underlying database table, so If it tries to insert a row that exists, it changes to update instead.
Something like this:
CREATE DEFINER = CURRENT_USER TRIGGER `Test`.`Job_BEFORE_INSERT` BEFORE INSERT ON `Job` FOR EACH ROW
BEGIN
INSERT INTO Job(id, createdAt, updatedAt, `name`,
version, ...)
VALUES(NEW.id, NEW.createdAt, NEW.updatedAt, NEW.name,
NEW.version, ...)
ON DUPLICATE KEY UPDATE
updatedAt=CURRENT_TIMESTAMP, `name`=VALUES(`name`), version=VALUES(version), ...;
END
But it generates an error on the first insert:
Error Code: 1442. Can't update table 'job' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
I read that you can't change the same table in a trigger or a stored procedure. Am I trying to make something impossible? Changing an insert into to an update if the row is existing?
Related
I created the following trigger in Mysql:
DELIMITER //
CREATE TRIGGER delete_G8_dados_indicadores_antes_insert
BEFORE INSERT
ON G8_dados_indicadores FOR EACH ROW
BEGIN
delete from G8_dados_indicadores where id_indicador=NEW.id_indicador and ano = NEW.ano;
END; //
DELIMITER ;
The idea is that before entering a record in G8_dados_indicadores table, the system triggers the trigger automatically removing existing records. But to run an insert, mysql returns the following error:
1442 - Can't update table 'G8_dados_indicadores' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
What can it be?
This is a known limitation in mysql, you have to find a workaround. In this particular instance, I would not even use a trigger, but either use replace into ... or insert ... on duplicate key update ... instead of an insert.
Replace into deletes the old row and inserts the new one, insert ... on duplicate key update ... does an update instead of an insert, if the record already exists.
I have the following trigger:
CREATE DEFINER=root#localhost TRIGGER after_insert_student AFTER INSERT ON
students FOR EACH ROW BEGIN
SET #cateID := NEW.ID ;
IF #cateID IS NOT NULL THEN
SELECT right(max(id), 3) INTO #firstid FROM students LIMIT 1;
SET #IDFOR = #firstid+1;
SET #DATEID = DATE_FORMAT(NOW(),'%y%d%m');
INSERT INTO students (CONCAT(#DATEID, #IDFOR), DATENEW)
VALUES(#IDFOR, NOW() );
END IF;
END
ERROR:
ERROR 1442: 1442: Can't update table 'students' in stored
function/trigger because it is already used by statement which invoked
this stored function/trigger.
You cannot update a table (students) where the trigger is invoked:
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.
Doing so will generate Error 1442:
Error Code: 1442
Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
If all you need is to set the fields value based on previous entries from the same table or other (using SELECT). You can use BEFORE INSERT ON students trigger, this way you can set/update/edit the field values using the NEW operator.
Is it because you are actually doing the insert on a before insert trigger?
Wouldn't you leave the insert up to the event that fired it?
You'd be inserting another student based on the student you have just inserted in the same table
Try rewriting with an AFTER INSERT ON, and update the record you have just created instead.
The error message says all: your trigger handles before insert events on the students table and you attempt to insert a new record into the students table from the trigger. Which would set off this very trigger again, which would insert another row into the same table... Shall I go on?
Change it to an after insert trigger or using the NEW.fieldname=... syntax you can modify the inserted values.
I have the following trigger:
CREATE DEFINER=root#localhost TRIGGER after_insert_student after INSERT ON
students FOR EACH ROW BEGIN
SET #NEWID := NEW.ID ;
if #NEWID IS NOT NULL THEN
INSERT INTO students SET ID = #NEWID;
else
INSERT INTO students SET ID = 001;
END IF
END
ERROR:
Error Code: 1442. Can't update table 'students' in stored
function/trigger because it is already used by statement which
invoked this stored function/trigger.
You cannot change a table while the INSERT trigger is firing. The INSERT might do some locking which could result in a deadlock. Also, updating the table from a trigger would then cause the same trigger to fire again in an infinite recursive loop. Both of these reasons are why MySQL prevents you from doing this.
To do this, please reference this link
You probably want a BEFORE INSERT trigger. Then instead of updating the table, just assign the desired value to NEW.ID.
The problem is that you can't write statement like
INSERT INTO students SET ID = #NEWID;
because it requires to know which columns you want to insert, or if not columns specified then you insert into all columns values etc.
INSERT INTO students values (#NEWID);
should work or if you want to stick to your SET ID then try to write something like
UPDATE students SET ID = #NEWID;
Hope this guides you to solution to your problem.
Solution: make it a BEFORE UPDATE ON trigger, and use NEW operator, it'll do the job - as all you want is if new ID is NULL set it to 001:
CREATE DEFINER=root#localhost TRIGGER after_insert_student
BEFORE INSERT ON students
FOR EACH ROW BEGIN
IF NEW.ID IS NULL THEN
SET ID = 001;
END IF;
END;
Cause: You cannot update a table (students) where the trigger is invoked:
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.
Doing so will generate Error 1442:
Error Code: 1442
Can't update table 'chatroompost' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
I have created a table test1 as
CREATE TABLE test1
(id INT,
name VARCHAR(20))
ENGINE=INNODB;
Now I want to delete a record from this table before inserting a new record having the same id(that is,record already existing with same id,then insert the new record) .I tried the code give below.
create trigger before_insert_test1 before insert
on test1
for each row
begin
delete from test1 where id=NEW.id;
end;
but it shows error
ERROR 1442 (HY000): Can't update table 'test1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Can anyone help.
thanks in advance
I don't think you can update/delete from the same table that you're inserting into. The table is being locked by the insert statement, even though you specified after insert. The insert transaction is not yet completed.
My suggestion would be to do a test and delete the record before you do the insert, or use the MySQL ON DUPLICATE KEY UPDATE statement if it applies
create trigger before_insert_test1 before insert on test1
DELETE FROM test1 WHERE id=NEW.id;
end;
You shan't need for loop, delete statement will delete every record with given id.
I'm using Mysql in phpMyAdmin,where i have to delete a entry from tableA if i insert a row with same primary key.I thought to do it in trigger of tableA BEFORE INSERT
For Ex,
if the tableA contains
1 Hai Hello
here 1 is the primary key
And now if i insert a row 1 Bye Hello then the trigger BEFORE INSERT will delete the old entry and then the new row (2nd) will be inserted. But Mysql has restriction of not being able to update a table inside a trigger defined for that same table.
It gives the error
#1442 - Can't update table 'tableA' in stored
function/trigger because it is already used by statement which invoked
this stored function/trigger.
So i changed my way, i called a procedure from trigger BEFORE INSERT of tableA and in that procedure i do the task what i thought to do in trigger. But unfortunately i'm getting the same error.
In trigger BEFORE INSERT i simply called the procedure as
CALL proce1(new.Reg_No);
In procedure i have done this
DECLARE toup integer;
select count(*) into toup from tableA where Reg_No=reg;/*Here Reg_No is primary key */
if toup > 0 then
delete from tableA where Reg_No=reg;
end if;
Need some other Idea to achieve this. Help Me.....
I don't like to use triggers so much because they are hard to manage somethimes. Also they will cause you a downgrade in performance. I am not against trigger as they can be handy in some cases.
In your case have you though of using REPLACE(....) or INSERT INTO .... ON DUPLICATE KEY UPDATE or even INSERT INTO IGNORE .....
REPLACE(....) will delete a record if a record is found and insert a new one with the same ID.
INSERT INTO .... ON DUPLICATE KEY UPDATE will allow you to override existing field if a duplicate is found.
INSERT INTO IGNORE ..... will allow you to ignore the new inserted row if one already exists
Since you mentioned in the comments that you are importing records from a file, then try to use LOAD DATA INFILE logic which will allow you to REPLACE field on duplicate
LOAD DATA LOCAL INFILE 'x3export.txt'
REPLACE INTO TABLE x3export