web-dev-qa-db-fra.com

Appeler une procédure stockée à partir d'un déclencheur

J'ai créé une procédure stockée dans mysql en utilisant la syntaxe suivante.

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 ;

Pour info j'ai considérablement simplifié la procédure stockée mais je sais que cela fonctionne sans aucun problème.

Ce que j'aimerais pouvoir faire, c'est configurer un déclencheur à partir de usergroup_comments qui fonctionne comme ceci.

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;

Mais pour une raison quelconque, chaque fois que je fais, mysql me lance une erreur qui n'est pas utile en déclarant qu'il y a une erreur de syntaxe à la ligne 4.

J'ai parcouru la documentation mysql et trouvé quelques informations sur les restrictions des déclencheurs mais je l'ai trouvée assez compliquée.

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

Toutes les idées seraient utiles.

17
Mark D

Il s'avère donc que c'est le problème qui m'a tourmenté pendant quelques heures, croyez-le ou non.

Je peux facilement définir une procédure appelée sp_set-comment_count. Cependant, lors de l'appel de ladite procédure, cela ne fonctionne pas de la même manière.

APPELER sp_set-comment_count (je peux seulement supposer que c'est parce que le serveur interprète le - comme un moins).

J'ai depuis changé le nom de la procédure stockée pour n'utiliser que des traits de soulignement et il semble avoir tout résolu.

8
Mark D

Il y a une bonne raison pour laquelle vous ne devez jamais appeler des procédures stockées à partir de déclencheurs.

Les déclencheurs sont, par nature, des procédures stockées. Leurs actions sont pratiquement difficiles à annuler . Même si toutes les tables sous-jacentes sont InnoDB, vous rencontrerez un volume proportionnel de verrous de ligne partagés et une intermittence gênante de verrous de ligne exclusifs. Tel serait le cas si les déclencheurs manipulaient des tables avec INSERT et UPDATE stagnant pour effectuer des tâches intensives MVCC à l'intérieur de chaque appel à un déclencheur .

N'oubliez pas que les déclencheurs nécessitent des frais généraux. En fait, selon MySQL Stored Procedure Programming , la page 256 sous la rubrique "Trigger Overhead" dit ce qui suit:

Il est important de se rappeler que, par nécessité, les déclencheurs ajoutent une surcharge à l'instruction DML à laquelle ils s'appliquent. la quantité réelle de surcharge dépendra de la nature du déclencheur, mais --- comme tous les déclencheurs MySQL s'exécutent POUR CHAQUE RANG --- la surcharge peut rapidement s'accumuler pour les instructions qui traitent un grand nombre de lignes. Vous devez donc éviter de placer des instructions SQL ou du code procédural coûteux dans les déclencheurs.

Une explication détaillée de la surcharge de déclenchement est donnée aux pages 529-531. Le point de conclusion de cette section indique ce qui suit:

La leçon à tirer est la suivante: puisque le code de déclenchement s'exécutera une fois pour chaque ligne affectée par une instruction DML, le déclencheur peut facilement devenir le facteur le plus important des performances DML. Le code à l'intérieur du corps du déclencheur doit être aussi léger que possible et - en particulier - toutes les instructions SQL dans le déclencheur doivent être prises en charge par des index chaque fois que possible.

J'ai expliqué d'autres aspects désagréables des déclencheurs dans un post précédent.

[~ # ~] résumé [~ # ~]

Je recommande fortement de ne pas appeler de procédures stockées à partir d'un déclencheur , même si MySQL le permet. Vous devriez vérifier les restrictions actuelles pour MySQL 5.5 .

24
RolandoMySQLDBA

S'il indique une erreur de syntaxe, il est fort probable que vous ayez oublié de modifier le délimiteur (comme vous l'avez fait pour la procédure stockée). Vous avez donc besoin

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

On dirait que la virgule après que AC est une erreur de syntaxe:

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