Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проблема с триггером в MySQL

1
30 июня 2012 года
kot_
7.3K / / 20.01.2000
Есть таблица и с ней связан триггер - который соотвественно срабатывает перед вставкой.
Код:
CREATE TABLE IF NOT EXISTS `sm_shelfstatuses` (
  `statusid` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `statusdate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `shelfid` BIGINT(20) NOT NULL,
  `thingstatusid` BIGINT(20) NOT NULL,
  `recepientid` INT(11) NOT NULL,
  `isactive` INT(11) NOT NULL DEFAULT '1',
  `changeraiting` INT(11) NOT NULL DEFAULT '10',
  `description` text,
  `whocreated` INT(11) NOT NULL,
  `statuspayment` INT(11) NOT NULL DEFAULT '0',
  `regionid` BIGINT(20) NOT NULL,
  PRIMARY KEY (`statusid`),
  KEY `shelfid` (`shelfid`),
  KEY `thingstatusid` (`thingstatusid`),
  KEY `recepientid` (`recepientid`),
  KEY `whocreated` (`whocreated`),
  KEY `regionid` (`regionid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=33 ;

--
-- Триггеры `sm_shelfstatuses`
--
DROP TRIGGER IF EXISTS `sm_shelfstatuses_before_ins_tr`;
DELIMITER //
CREATE TRIGGER `sm_shelfstatuses_before_ins_tr` BEFORE INSERT ON `sm_shelfstatuses`
 FOR EACH ROW BEGIN
     UPDATE `sm_shelfstatuses`  SET `isactive` = 0 WHERE `shelfid` = NEW.`shelfid`;
END
//
DELIMITER ;

--
-- Ограничения внешнего ключа сохраненных таблиц
--

--
-- Ограничения внешнего ключа таблицы `sm_shelfstatuses`
--
ALTER TABLE `sm_shelfstatuses`
  ADD CONSTRAINT `sm_shelfstatuses_fk4` FOREIGN KEY (`regionid`) REFERENCES `sm_regions` (`regionId`),
  ADD CONSTRAINT `sm_shelfstatuses_fk` FOREIGN KEY (`shelfid`) REFERENCES `sm_thingshelf` (`shelfid`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `sm_shelfstatuses_fk1` FOREIGN KEY (`thingstatusid`) REFERENCES `sm_sprthingshelfstatuses` (`thingstatusid`),
  ADD CONSTRAINT `sm_shelfstatuses_fk2` FOREIGN KEY (`recepientid`) REFERENCES `sm_users` (`id`),
  ADD CONSTRAINT `sm_shelfstatuses_fk3` FOREIGN KEY (`whocreated`) REFERENCES `sm_users` (`id`);
но при попытке выполнить вставку данных я получаю ошибку General error: 1442. Can't update table ... in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Есть у кого какие нибудь идеи в чем может быть причина ошибки?
Версия сервера: 5.5.16
Версия MySQL-клиента: mysqlnd 5.0.8-dev - 20102224 - $Revision: 310735
277
30 июня 2012 года
arrjj
1.7K / / 26.01.2011
Это не баг это задокумментированная фишка:
Цитата:

A stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.



Реализуй логику в скрипте или вставку через stored procedure с соответствующими проверками.

1
30 июня 2012 года
kot_
7.3K / / 20.01.2000
да с логикой понятно. в скрипт ее сейчас и вынес. Но чтото либо я чего не понимаю - либо нахуй такие триггеры не понятна логика разработчиков.
277
30 июня 2012 года
arrjj
1.7K / / 26.01.2011
Ну может у них просто не получилось? ^^
10
01 июля 2012 года
Freeman
3.2K / / 06.03.2004
Программисты, которые не понимают рекурсию, не понимают рекурсию.

Наверное, в где-то доке должно быть описано, что изменять ту же таблицу, на которую висит триггер -- нарушение логики транзакций. В некоторых СУБД можно эмулировать операции DML, полностью подменяя их триггерами instead of. Обычно это доступно только для представлений, как в Oracle. Есть даже мнение, что конечной программе не нужно давать доступ к таблицам, а только к представлениям с триггерами instead of, реализующими нужную логику.
1
01 июля 2012 года
kot_
7.3K / / 20.01.2000
Цитата: Freeman

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


сложно сказать. наверное гдето описано. с одной стороны да - так как триггер работает вне транзакции - то попытка модифицировать данные в данной таблице может запросто привести к неоднозначности. в общем как страшно жить.

277
01 июля 2012 года
arrjj
1.7K / / 26.01.2011
Цитата: kot_
Цитата: Freeman

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


сложно сказать. наверное гдето описано....


угу, написано - я ссылку во втором посте давал.

10
01 июля 2012 года
Freeman
3.2K / / 06.03.2004
Цитата: kot_
так как триггер работает вне транзакции


А вот не факт. В Oracle триггер всегда внутри транзакции, потому что транзакции принудительные, и нет транзакции -- нет и сеанса пользователя.

Глядя на последние изменения MySQL, наблюдаемые по форумам и от знакомых, показалось, что после покупки Oracle хочет подтянуть его к (своему?) стандарту, -- хотя бы в тех рамках, где можно. Триггеры, работающие в транзакции, похожи на одно из таких изменений. Это если считать, что запрет на изменение таблиц -- именно из-за транзакций, а не желания разработчиков насолить пользователям.

Я доку не читал, поэтому только предполагаю. :-)

1
02 июля 2012 года
kot_
7.3K / / 20.01.2000
сложно сказать что хочет Oracle - но факт что сделать то что мне необходимо в yii можно используя beforeSave. По поводу транзакций и триггеров - на MySQL триггер работает все же в контексте транзакции - это я напутал. Но не смотря на это - модифицировать данные в таблице на которую повешен триггер - таки нельзя. Ну и хер с ним.
72K
02 июля 2012 года
CorsaiR
59 / / 07.03.2012
А просто
 
Код:
SET NEW.isactive = 0;
в триггере не проканает?
1
02 июля 2012 года
kot_
7.3K / / 20.01.2000
Цитата: CorsaiR
А просто
 
Код:
SET NEW.isactive = 0;
в триггере не проканает?


проканает наверняка.
стесняюсь спросить - а нахера? :)
мне то надо что бы в ноль были установлены как раз таки те записи, которые в таблице уже есть.

72K
02 июля 2012 года
CorsaiR
59 / / 07.03.2012
Действительно (
Почитал поподробнее о триггерах в мускуле - сыровато. Есть очень неприятные моменты:

Note
Currently, cascaded foreign key actions do not activate triggers.

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог