質問

この回答のクリーンアップ 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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top