ТРИГГЕРЫ, которые приводят к сбою INSERT? Возможное?

Убрав этот ответ, я немного узнал о TRIGGER s и хранил процедуры в MySQL, но был ошеломлен тем, что, хотя триггеры BEFORE INSERT и BEFORE UPDATE могут изменять данные, они, похоже, не могут привести к сбою вставки / обновлению (т. Е. Проверка ). В этом конкретном случае я смог заставить это работать, манипулируя данными таким образом, чтобы вызвать дубликат первичного ключа, который в данном конкретном случае имел смысл, но не обязательно имеет смысл в общем смысле.

Возможна ли такая функциональность в MySQL? В любой другой СУБД (мой опыт ограничен MySQL с грустью)? Возможно, синтаксис стиля THROW EXCEPTION ?

Из этого сообщения в блоге

MySQL Triggers: как вы прерываете INSERT, UPDATE или DELETE с помощью триггера? На #mysql EfNet кто-то спросил:

Как заставить триггер прерывать операцию, если мое бизнес-правило выходит из строя?

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

SP 11. У SP есть выражение «raise» для «повышения ошибок приложения»? Извините, не сейчас. Стандартные SQL-запросы SIGNAL и RESIGNAL находятся на TODO.

Возможно, MySQL 5.2 будет включать в себя инструкцию SIGNAL, которая приведет к тому, что этот хак украден прямо из устаревшего программирования MySQL с сохраненной процедурой. Что такое взлом? Вы заставите MySQL попытаться использовать столбец, который не существует. Гадкий? Да. Это работает? Конечно.

 CREATE TRIGGER mytabletriggerexample BEFORE INSERT FOR EACH ROW BEGIN IF(NEW.important_value) < (fancy * dancy * calculation) THEN DECLARE dummy INT; SELECT Your meaningful error message goes here INTO dummy FROM mytable WHERE mytable.id=new.id END IF; END; 

Вот как я это сделал. Обратите внимание на SET NEW='some error'; , MySQL сообщит вам, что «Variable« new »не может быть установлен в значение« Ошибка: не удается удалить этот элемент. В таблице продаж есть этот элемент ».

Вы можете заманить это в свой код, а затем показать полученную ошибку 🙂

 DELIMITER $$ DROP TRIGGER IF EXISTS before_tblinventoryexceptionreasons_delete $$ CREATE TRIGGER before_tblinventoryexceptionreasons_delete BEFORE DELETE ON tblinventoryexceptionreasons FOR EACH ROW BEGIN IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblinventoryexceptionreasons = old.idtblinventoryexceptionreasons) > 0 THEN SET NEW='Error: Cannot delete this item. There are records in the inventory exception reasons table with this item.'; END IF; END$$ DELIMITER ; DELIMITER $$ DROP TRIGGER IF EXISTS before_storesalesconfig_delete $$ CREATE TRIGGER before_storesalesconfig_delete BEFORE DELETE ON tblstoresalesconfig FOR EACH ROW BEGIN IF (SELECT COUNT(*) FROM tblstoresales WHERE tblstoresales.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0 THEN SET NEW='Error: Cannot delete this item. There are records in the sales table with this item.'; END IF; IF (SELECT COUNT(*) FROM tblinventory WHERE tblinventory.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0 THEN SET NEW='Error: Cannot delete this item. There are records in the inventory table with this item.'; END IF; IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0 THEN SET NEW='Error: Cannot delete this item. There are records in the inventory exceptions table with this item.'; END IF; IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0 THEN SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.'; END IF; END$$ DELIMITER ; DELIMITER $$ DROP TRIGGER IF EXISTS before_tblinvoice_delete $$ CREATE TRIGGER before_tblinvoice_delete BEFORE DELETE ON tblinvoice FOR EACH ROW BEGIN IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblinvoice = old.idtblinvoice) > 0 THEN SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.'; END IF; END$$ DELIMITER ; 

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

Если есть ошибка, вы можете заставить MySQL использовать СИГНАЛ , но если вы не укажете его как class SQLEXCEPTION, тогда ничего не произойдет, поскольку не все SQLSTATE считаются плохими, и даже тогда вам придется убедитесь, что RESIGNAL, если у вас есть какие-либо вложенные блоки BEGIN / END.

В качестве альтернативы и, вероятно, еще проще, внутри вашего триггера, объявить обработчик выхода и отменить исключение.

 CREATE TRIGGER `my_table_AINS` AFTER INSERT ON `my_table` FOR EACH ROW BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION RESIGNAL; DECLARE EXIT HANDLER FOR SQLWARNING RESIGNAL; DECLARE EXIT HANDLER FOR NOT FOUND RESIGNAL; -- Do the work of the trigger. END 

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

Это работает с любой версией 5.5+.

Это приведет к прерванию вашего INSERT путем создания исключения (с http://www.experts-exchange.com/Database/MySQL/Q_23788965.html )

 DROP PROCEDURE IF EXISTS `MyRaiseError`$$ CREATE PROCEDURE `MyRaiseError`(msg VARCHAR(62)) BEGIN DECLARE Tmsg VARCHAR(80); SET Tmsg = msg; IF (CHAR_LENGTH(TRIM(Tmsg)) = 0 OR Tmsg IS NULL) THEN SET Tmsg = 'ERROR GENERADO'; END IF; SET Tmsg = CONCAT('@@MyError', Tmsg, '@@MyError'); SET @MyError = CONCAT('INSERT INTO', Tmsg); PREPARE stmt FROM @MyError; EXECUTE stmt; DEALLOCATE PREPARE stmt; END$$ 

Применение:

 call MyRaiseError('Here error message!'); 

Doen’t не работает в триггерах (динамический SQL не разрешен в сохраненной функции или триггере)

Я использую очень грязное решение:

If NEW.test=1 then CALL TEST_CANNOT_BE_SET_TO_1; end if;

Когда test = 1 Mysql выдает следующее исключение:

ПРОЦЕДУРА adminatie.TEST_CANNOT_BE_SET_TO_1 не существует

Не сложный, но быстрый и полезный.

в MS SQL вы можете заставить его работать с использованием правильного синтаксиса:

 IF UPDATE(column_name) BEGIN RAISEERROR ROLLBACK TRAN RETURN END 

http://msdn.microsoft.com/en-us/magazine/cc164047.aspx

  • Динамический шаблон изменения данных
  • Как вызвать клик по ссылке с помощью jQuery
  • Событие изменения триггера () при установке значения с помощью функции val ()
  • Передача идентификатора пользователя в триггеры PostgreSQL
  • могу ли я запустить триггер для оператора select в mysql?
  • Выбросить ошибку в триггере MySQL
  • Давайте будем гением компьютера.