MySQL - триггер для обновления той же таблицы после вставки
Вот что я пытаюсь сделать:
Когда в таблицу ACCOUNTS
добавлен новый INSERT
, мне нужно обновить строку в ACCOUNTS
, где pk
= NEW.edit_on
, установив status='E'
для обозначения того, что конкретная (старая) учетная запись имеет был отредактирован.
DELIMITER $$
DROP TRIGGER IF EXISTS `setEditStatus`$$
CREATE TRIGGER `setEditStatus` AFTER INSERT on ACCOUNTS
FOR EACH ROW BEGIN
update ACCOUNTS set status='E' where ACCOUNTS.pk = NEW.edit_on ;
END$$
DELIMITER ;
Требование НЕ, что я манипулирую недавно вставленным столбцом, но уже существующий столбец с pk = NEW.edit_on
Однако я не могу обновить ту же таблицу: Can't update table ACCOUNTS ... already used by the statement that invoked this trigger
Пожалуйста, предложите обходное решение
PS: Я уже прошел Обновление таблицы в триггере после обновления в той же таблице, Вставить в ту же таблицу триггер mysql, Обновить с помощью триггера вставки в той же таблице и триггер mysql с вставкой и обновлением после вставки в таблицу, но они, похоже, не отвечают на мой вопрос.
Edit
ACCOUNTS
Таблица:
CREATE TABLE `ACCOUNTS` (
`pk` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(9) unsigned NOT NULL,
`edit_on` bigint(10) unsigned DEFAULT NULL,
`status` varchar(1) NOT NULL DEFAULT 'A',
PRIMARY KEY (`pk`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=2147483726 DEFAULT CHARSET=latin1
Ответы
Ответ 1
Кажется, что вы не можете сделать все это в триггере. Согласно документации:
Внутри хранимой функции или триггера запрещено изменять таблицу, которая уже используется (для чтения или записи) оператором, который вызвал функцию или триггер.
Согласно этому ответу кажется, что вы должны:
создайте хранимую процедуру, которая вставляет в /Updates целевую таблицу, затем обновляет другую строку (и), все в транзакции.
С сохраненным процессом вы будете фиксировать изменения вручную (вставлять и обновлять). Я не делал этого в MySQL, но этот пост выглядит хорошим примером.
Ответ 2
Вот как я обновляю строку в той же таблице при вставке
activationCode и email - это строки в таблице USER.
На вставке я не укажу значение для кода активации, оно будет создано на лету mysql.
Измените "имя пользователя" на свое имя пользователя mysql и "db_name" с вашим именем db.
CREATE DEFINER=`username`@`localhost`
TRIGGER `db_name`.`user_BEFORE_INSERT`
BEFORE INSERT ON `user`
FOR EACH ROW
BEGIN
SET new.activationCode = MD5(new.email);
END
Ответ 3
Имела ту же проблему, но ей пришлось обновить столбец с идентификатором, который должен был войти, поэтому вы можете сделать обновление, которое должно быть выполнено ПЕРЕД И ПОСЛЕ НЕ ПРЕЖДЕ ЧЕМ не было идентификатора, поэтому я сделал этот трюк
DELIMITER $$
DROP TRIGGER IF EXISTS `codigo_video`$$
CREATE TRIGGER `codigo_video` BEFORE INSERT ON `videos`
FOR EACH ROW BEGIN
DECLARE ultimo_id, proximo_id INT(11);
SELECT id INTO ultimo_id FROM videos ORDER BY id DESC LIMIT 1;
SET proximo_id = ultimo_id+1;
SET NEW.cassette = CONCAT(NEW.cassette, LPAD(proximo_id, 5, '0'));
END$$
DELIMITER ;
Ответ 4
В последней записи; это еще один трюк:
SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_schema = ... and table_name = ...
Ответ 5
Вместо этого вы можете использовать перед вставкой и получить max pkid для конкретной таблицы, а затем обновить запись таблицы maximium pkid.
Ответ 6
DELIMITER $$
DROP TRIGGER IF EXISTS 'setEditStatus'$$
CREATE TRIGGER 'setEditStatus' **BEFORE** INSERT on ACCOUNTS
FOR EACH ROW BEGIN
SET NEW.STATUS = 'E';
END$$
DELIMITER ;