質問
この回答のクリーンアップ MySQLの TRIGGER
およびストアドプロシージャについて少し学びましたが、 BEFORE INSERT
および BEFORE UPDATE
トリガーが発生したことに驚かされましたデータを変更できる可能性がありますが、挿入/更新を失敗させることはできません(検証など)。この特定のケースでは、主キーの重複を引き起こすようにデータを操作することでこれを機能させることができました。この特定のケースでは意味がありますが、必ずしも一般的な意味では意味がありません。
この種の機能はMySQLで可能ですか?他のRDBMSで(私の経験は悲しいことにMySQLに限定されています)?おそらく THROW EXCEPTION
スタイルの構文ですか?
解決
こちらからブログ投稿
MySQLトリガー:INSERT、UPDATE、またはDELETEをどのように中止しますか 引き金? EfNetの#mysqlの誰か 質問:
ビジネスルールが失敗した場合、トリガーで操作を中止するにはどうすればよいですか
MySQL 5.0および5.1では、以下が必要です。 いくつかの策略に頼って、 トリガー失敗と意味のある配信 エラーメッセージ。格納されたMySQL 手順に関するよくある質問には、エラーについての説明があります 処理:
SP 11. SPには“ raise”がありますか? “アプリケーションエラーの発生&#8221 ;?申し訳ありませんが、現在ではありません。 SQL標準のSIGNALおよびRESIGNALステートメントはTODOにあります。
おそらくMySQL 5.2にはSIGNALが含まれるでしょう このハックを作成するステートメント MySQL Storedから直接盗まれた プロシージャプログラミングは廃止されました。何 ハックは何ですか?あなたは強制するつもりです 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は&quot; Variable 'new'を 'Error:Cannot delete this item。'の値に設定できないことを通知します。 salesテーブルにこのアイテムのレコードがあります。 '&quot;
これをコードにトラップして、結果のエラーを表示できます:)
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に SIGNAL 。ただし、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以降で動作します。
これは、 http://から例外を発生させることにより、INSERTを中止します。 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!');
トリガーでは機能しません (動的SQLはストアド関数またはトリガーでは許可されていません)
非常に汚い解決策を使用しています:
NEW.test = 1の場合
CALL TEST_CANNOT_BE_SET_TO_1;
終了する場合;
test = 1の場合、Mysqlは次の例外をスローします:
PROCEDURE administratie.TEST_CANNOT_BE_SET_TO_1は存在しません
洗練されていませんが、高速で便利です。
MS SQLでは、適切な構文を使用して動作させることができます。
IF UPDATE(column_name)
BEGIN
RAISEERROR
ROLLBACK TRAN
RETURN
END