Могу ли я использовать транзакцию как возможность в триггере MySQL - PullRequest
5 голосов
/ 13 февраля 2012

У меня есть триггер вставки, который берет набор значений столбцов из строк в таблице A и вставляет некоторые из них в таблицу B, оставаясь в таблице C. Мне нужна эта операция, чтобы она была транзакцией, в которой при наличии какой-либо ошибки во время данных вставляется в таблицу B, а не C, всю операцию вставки следует откатить.

Я изучил руководство, и на последней из этой страницы написано, что транзакция запрещена в триггерах

Есть ли способ достичь того, чего я хочу в MySQL.

Ответы [ 2 ]

4 голосов
/ 31 июля 2012

Да, вы можете, но то, как вы это сделаете, зависит от вашей версии.

Прежде всего, триггеры сами являются транзакционными;в вашей ситуации у вас есть триггер вставки, который выполняет еще две вставки.Если один из этих сбоев, вы получите желаемый эффект.

Рассмотрим следующий пример:

CREATE TABLE a (colA INT);
CREATE TABLE b (colB INT);
CREATE TABLE c (colC INT);
delimiter :
CREATE TRIGGER testtrig BEFORE INSERT ON a
  FOR EACH ROW BEGIN
    INSERT INTO b(colB) VALUES(NEW.colA);
    INSERT INTO c(banana) VALUES (NEW.colA); -- note the faulty column name
END;:
delimiter ;

Теперь, когда я запускаю вставку, которая не удалась, это происходит:

mysql> INSERT INTO a VALUES (5);
ERROR 1054 (42S22): Unknown column 'banana' in 'field list'
mysql> SELECT * FROM a;
Empty set (0.00 sec)

Это соответствует желаемому результату.

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

  • В MySQL 5.5 вы можете использовать SIGNAL механизм, чтобы вызвать ошибку из вашего триггера, таким образом вызывая сбой всей вставки.
  • До MySQL 5.5 вы могли генерировать преднамеренную ошибку для сбоя триггера.1021 *

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

0 голосов
/ 02 июля 2015

По умолчанию вы получаете то, что просили - любая ошибка в триггере приводит к сбою оператора.Поэтому, если в операторе есть транзакция, вы получаете откат данных непосредственно перед этим оператором.Если транзакции нет, значит, нет.

Возможно, поэтому создание или завершение транзакции в триггере не разрешено.

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

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

...