web-dev-qa-db-ja.com

トリガーからストアドプロシージャを呼び出す

次の構文を使用して、mysqlにストアドプロシージャを作成しました。

DROP PROCEDURE IF EXISTS `sp-set_comment_count`;

DELIMITER $$

CREATE PROCEDURE `sp_set-comment_count` (IN _id INT)
BEGIN
   -- AC   - AllCount
   DECLARE AC INT DEFAULT 0;

   SELECT COUNT(*) AS ac
     INTO AC
     FROM usergroups AS ug
LEFT JOIN usergroup_comments AS ugm ON ugm.`gid` = ug.`id`
LEFT JOIN mediagallery AS dm ON ugm.mid = dm.`id`
    WHERE dm.`status` NOT IN (200, 201, 202, 203, 204, 205)
      AND ug.`id` = _id;

   UPDATE usergroups
      SET allCount = AC,
    WHERE usergroups.`id` = _id;

END $$
DELIMITER ;

参考までに、ストアドプロシージャを大幅に簡略化しましたが、問題なく動作することはわかっています。

私ができることは、このように機能するusergroup_commentsからトリガーを設定することです。

DROP TRIGGER IF EXISTS `usergroups_comments_insert` 

CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
    FOR EACH ROW
    BEGIN
       CALL sp-set-comment_count(NEW.`gid`);
    END;

しかし、何らかの理由で、mysqlを実行するたびにエラーがスローされます。これは、4行目に構文エラーがあることを示すのに役立ちません。

私はmysqlのドキュメントを調べ、トリガーの制限に関する情報を見つけましたが、かなり複雑であることがわかりました。

http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html

どんなアイデアも役に立ちます。

17
Mark D

ですから、これが数時間私を悩ませてきた問題であり、信じられないかもしれません。

Sp_set-comment_countというプロシージャを簡単に定義できます。ただし、上記のプロシージャを呼び出すと、同じように機能しません。

CALL sp_set-comment_count(これは、サーバーが-をマイナスとして解釈するためです).

その後、ストアドプロシージャ名をアンダースコアのみを使用するように変更し、すべてを解決したようです。

8
Mark D

トリガー内からストアドプロシージャを呼び出すべきではないのには大きな理由があります。

トリガーは本来、ストアドプロシージャです。そのアクションをロールバックするのは事実上困難です 。基礎となるすべてのテーブルがInnoDBである場合でも、比例した量の共有行ロックが発生し、排他的行ロックによる煩わしい断続性が発生します。これは、トリガーがINSERTおよびUPDATEを停滞させてヘビーデューティーを実行するテーブルを操作している場合に当てはまります [〜#〜] mvcc [〜#〜] トリガーへの各呼び出し内 =。

トリガーにはオーバーヘッドが必要であることを忘れないでください。実際、 MySQLストアドプロシージャプログラミング によると、256ページの「トリガーオーバーヘッド」の下には次のように書かれています。

トリガーは、必要に応じて、適用するDMLステートメントにオーバーヘッドを追加することを覚えておくことが重要です。実際のオーバーヘッドの量はトリガーの性質に依存しますが、---すべてのMySQLトリガーがFOR EACH ROWを実行するため---オーバーヘッドは、大量の行を処理するステートメントに対して急速に蓄積する可能性があります。したがって、トリガーに高価なSQLステートメントや手続きコードを配置することは避けてください。

トリガーオーバーヘッドの詳しい説明は、529〜531ページに記載されています。そのセクションの結論は次のとおりです。

ここでの教訓は次のとおりです。トリガーコードはDMLステートメントの影響を受ける行ごとに1回実行されるため、トリガーは簡単にDMLパフォーマンスの最も重要な要素になる可能性があります。トリガー本体内のコードは、可能な限り軽量である必要があり、特にトリガー内のSQLステートメントは、可能であればいつでもインデックスでサポートされる必要があります。

以前の投稿でトリガーの他の厄介な側面を説明しました。

[〜#〜]要約[〜#〜]

MySQLで許可されている場合でも、トリガーからストアドプロシージャを呼び出さないことを強く推奨します。 MySQL 5.5の現在の制限を確認する必要があります

24
RolandoMySQLDBA

構文エラーが表示されている場合は、(ストアドプロシージャの場合と同様に)区切り文字を変更するのを忘れている可能性があります。だからあなたは必要です

DELIMITER $$
CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
FOR EACH ROW
BEGIN
   CALL sp_set_count(NEW.`gid`);
END;
$$
5
a1ex07

ACの後のコンマは構文エラーのようです。

UPDATE usergroups
   SET allCount = AC,
 WHERE ........
1
user22800