问题
I need to make trigger that transfers rows from table to another table with same name rows when row data value checked is 1 so it is checked to be moved. This should happen when something is inserted or altered. Any ideas?
回答1:
A MySQL error 1442:
Error Code: 1442. Can't update table 'xyz' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Will occur in cases of cascading or recursive like trigger calls due to the server knowing it is in the same call stack.
About the best you can do is leverage an event cleanup strategy where you choose the frequency of your choosing. If you use it, remember that it leverages the Global event scheduler and you can't forget it is running. Also, in most shared hosting environments, events aren't supported due to shared resources (people tend to abuse them and it affects everyone).
That said,
Schema:
create table orig101
( id int auto_increment primary key,
thing1 varchar(100) not null,
checked int not null
);
create table copy101
( id int primary key,
thing1 varchar(100) not null,
checked int not null
);
Event:
DROP EVENT IF EXISTS cleanUpCopied;
DELIMITER $$
CREATE EVENT cleanUpCopied
ON SCHEDULE EVERY 2 MINUTE STARTS '2016-01-01 00:00:00'
ON COMPLETION PRESERVE
DO
BEGIN
DELETE FROM orig101 WHERE checked=1;
END $$
DELIMITER ;
-- -------------------------------------------------
select @@event_scheduler; -- mine is currently OFF
SET GLOBAL event_scheduler = ON; -- turn her on and confirm below
select @@event_scheduler; -- yep it is ON
Triggers:
DROP TRIGGER IF EXISTS aft_ins_orig;
delimiter $$
CREATE TRIGGER aft_ins_orig AFTER INSERT ON orig101
FOR EACH ROW
BEGIN
IF NEW.checked=1 THEN
INSERT IGNORE copy101 (id,thing1,checked)
SELECT NEW.id,NEW.thing1,NEW.checked;
END IF;
END;$$
delimiter ;
-- -------------------------------------------------
DROP TRIGGER IF EXISTS aft_upd_orig;
delimiter $$
CREATE TRIGGER aft_upd_orig AFTER UPDATE ON orig101
FOR EACH ROW
BEGIN
IF NEW.checked=1 THEN
INSERT IGNORE copy101 (id,thing1,checked)
SELECT NEW.id,NEW.thing1,NEW.checked;
END IF;
END;$$
delimiter ;
Test:
truncate orig101;
truncate copy101;
INSERT orig101 (thing1,checked) values ('frog',0);
select * from orig101; -- 1 row
select * from copy101; -- 0 rows
INSERT orig101 (thing1,checked) values ('fish',1); -- when evt fires, cleanup occurs
select * from orig101; -- until evt fires, checked=1 row(s) still there
select * from copy101;
INSERT orig101 (thing1,checked) values ('fish2',1); -- when evt fires, cleanup occurs
INSERT orig101 (thing1,checked) values ('fish3',1); -- when evt fires, cleanup occurs
INSERT orig101 (thing1,checked) values ('fish4',1); -- when evt fires, cleanup occurs
INSERT orig101 (thing1,checked) values ('fish5',1); -- when evt fires, cleanup occurs
select * from orig101; -- until evt fires, checked=1 row(s) still there
select * from copy101;
UPDATE orig101 set checked=1 where id=1;
-- Tweak the frequency of event firing (say every minute, or every hour, whatever)
I have about 3 links off my profile page for events. Good luck.
来源:https://stackoverflow.com/questions/39038316/mysql-trigger-to-move-row-from-table-to-indentical-other-table