web-dev-qa-db-ja.com

MySqlトリガーでINSERT操作を中止する方法は?

URLとそのパラメーターを表す文字列を含むテーブルがあります。問題は、URLとパラメータ文字列をテーブルの一意の制約にしたいことです。つまり、同じURLとパラメータ文字列を持つエントリはありません。パラメータ文字列は任意の長さにすることができます(MySqlキーの最大長である800バイトよりも長いため、エラーをスローするため、Unique(url、params)は使用できません...)。

トリガーを使用してこれを行うことを考えましたが、トリガーが挿入が重複エントリを挿入しようとしていることをトリガーが検出した場合、どのように例外をスローし、エラーを発生させますか? MySqlと同じようにMySqlExceptionがスローされるようにしたいのですが、C#コードでキャッチできます。

助けが必要なトリガーに2つの部分があります。.. C#に例外をスローする中止... C#に例外などをスローする方法を教えてください。 ...挿入を許可...-重複するエントリがない場合、どうすれば挿入を許可できますか?

トリガーコードは以下のとおりです。

CREATE TRIGGER urls_check_duplicates
BEFORE INSERT ON urls
FOR EACH ROW

BEGIN
DECLARE num_rows INTEGER;

SELECT COUNT(*)
INTO num_rows
FROM urls
WHERE url = NEW.url AND params = NEW.params;

IF num_rows > 0 THEN
   ... ABORT/throw exception to C# ...
ELSE
   ... Allow insert ...
END
31
johnrl

トリガーに関するmysqlドキュメントのコメント は、mysqlにそのような機能がないことを示唆しています。あなたができる最善のことは、トリガーエラー用に別のテーブルを作成することです 同じページで提案されているように

8
soulmerge

私はこれに遭遇し、解決策は機能しますが、後でより良い解決策のように感じられるものに遭遇しました。この質問が最初に回答されたとき、これは選択肢ではなかったと思います。

CREATE TRIGGER `TestTable_SomeTrigger`
BEFORE UPDATE ON `test_table`
FOR EACH ROW
BEGIN
    DECLARE msg VARCHAR(255);
    IF (SomeTestToFail = "FAIL!") THEN
        set msg = "DIE: You broke the rules... I will now Smite you, hold still...";
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
    END IF;

    -- Do any other code here you may want to occur if it's all OK or leave blank it will be
    --  skipped if the above if is true
END$$

これにより、トラップできるNice(またはevil!)エラーメッセージが返されます。この詳細については、次を参照してください: http://dev.mysql.com/doc/refman/5.5/en/signal.html

これが他の誰かの役に立つことを願っています!

70
GazB

テーブル定義がNOT NULL値に対するものである場合、NEWをNULLに設定すると、事実上挿入が行われません。これを正しく機能させるには、厳密なSQLモードをオンにする必要がある場合があります。

6
g33kz0r