MySQL Trigger - удалить после обновления - PullRequest
2 голосов
/ 25 августа 2011

Для тестового примера в одном проекте я должен удалить запись, если одно из полей удовлетворяет одному из условий. Самым простым кажется простой триггер:

delimiter $$
drop trigger w_leb_go $$

create trigger w_leb_go after update on test
for each row
begin
set @stat=NEW.res;
set @id=NEW.id;
IF @stat=3 THEN
  delete from test where id=@id;
END IF;
end$$

delimiter ;

Но, как я подозреваю, получил ошибку:

обновить набор тестов res = 3, где id = 1;
ОШИБКА 1442 (HY000): Невозможно обновить таблицу 'test' в сохраненной функции / триггере, поскольку она уже используется оператором, который вызвал эту сохраненную функцию / триггер.

Как еще можно сделать, только имея доступ к базе данных? Я имею в виду, что я не должен менять проверенное приложение.

Ответы [ 3 ]

1 голос
/ 25 августа 2011

Что вам может понадобиться, это использовать «ПЕРЕД ВСТАВКОЙ» триггера, чтобы проверить, является ли добавляемая запись недопустимой.

В этом вопросе SO даются некоторые подробности о том, как ввести неправильную запись: Запретить вставку

Альтернативой является изменение вашей программы для вставки записи в другую таблицу, которая имеет триггер для очистки нужной таблицы.

0 голосов
/ 05 апреля 2016

Мои несколько центов: - Добавление «удаленного» столбца считается изменением в структуре таблицы. Следовательно, не рекомендуется, если это не новая разработка.

Если это устаревшее приложение, то лучше - добавьте напоминание об удалении во временную таблицу и проверьте эту таблицу после оператора обновления.

0 голосов
/ 25 августа 2011

Внутри триггера вы не можете изменить таблицу, к которой принадлежит триггер.
Вы также не можете что-то косвенно изменить эту таблицу.

Однако есть несколько других вещей, которые вы можете сделать. Если вы не удаляете строку, а добавляете поле deleted, тогда вы можете пометить как удаленное, вот так.

delimiter $$
drop trigger w_leb_go $$

CREATE TRIGGER w_leb_go BEFORE UPDATE ON test FOR EACH ROW
BEGIN
  IF NEW.res=3 THEN
    SET NEW.deleted = 1;
  END IF;
END$$

delimiter ;

Обратите внимание, что триггер должен быть before, если вы хотите изменить что-либо в строке.

В качестве альтернативы вы можете добавить напоминание об удалении во временную таблицу и проверить эту таблицу после оператора обновления.

CREATE TRIGGER au_test_each AFTER UPDATE ON test FOR EACH ROW
BEGIN
  IF NEW.res=3 THEN
    INSERT INTO deletion_list_for_table_test (test_id) VALUE (NEW.id);
  END IF;
END$$

Теперь вам нужно изменить оператор обновления на:

START TRANSACTION;
UPDATE test SET whatever to whichever;
DELETE test FROM test
INNER JOIN deletion_list_for_table_test dt ON (test.id = dt.test_id);
DELETE FROM deletion_list_for_table_test WHERE test_id > 0 /*i.e. everything*/
COMMIT;

Конечно, если вы отметите строк, вы можете упростить код удаления до:

START TRANSACTION;
UPDATE test SET whatever to whichever;
DELETE FROM test WHERE deleted = 1;
COMMIT;
...