it-swarm-eu.dev

Vyvolání uložené procedury ze spouště

Vytvořil jsem uloženou proceduru v mysql pomocí následující syntaxe.

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 ;

FYI Uloženou proceduru jsem velmi zjednodušil, ale vím, že to funguje bez problémů.

Co bych chtěl udělat, je nastavit spouštěč z usergroup_comments, který funguje takto.

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;

Ale z nějakého důvodu pokaždé, když dělám mysql, vyvolá na mě chybu, která je méně než užitečná, když uvádí, že v řádku 4 je chyba syntaxe.

Pročetl jsem si dokumentaci mysql a našel jsem několik informací o omezeních spouště, ale zjistil jsem, že je docela spletitý.

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

Jakékoli nápady by byly užitečné.

17
Mark D

Ukázalo se tedy, že toto je problém, který mi na pár hodin trápil, že tomu věřím nebo ne.

Dokážu snadno definovat postup nazvaný sp_set-comment_count. Avšak při volání uvedené procedury to nefunguje stejným způsobem.

CALL sp_set-comment_count (Můžu jen předpokládat, že je to proto, že server interpretuje - jako mínus).

Od té doby jsem změnil název uložené procedury tak, aby používal pouze podtržítka, a zdá se, že vše vyřešilo.

8
Mark D

Existuje velký důvod, proč byste nikdy neměli volat uložené procedury zv rámci spouště.

Spouštěče jsou ze své podstaty uložené procedury. Jejich akce je prakticky těžké vrátit zpět . I když jsou všechny podkladové tabulky InnoDB, zažijete poměrný objem sdílených zámků řádků a nepříjemné přerušování z exkluzivních zámků řádků. Tak by tomu bylo v případě, kdyby spouštěče manipulovaly s tabulkami s INSERTy a UPDATE, které byly stagnovány, aby vykonávaly těžkou práci MVCC uvnitř každého hovoru na spoušť .

Nezapomeňte, že Triggers vyžadují režii. Ve skutečnosti, podle MySQL Programování uložených procedur , stránka 256 pod hlavičkou „Trigger Overhead“ říká:

Je důležité si uvědomit, že spouští nutně spouští příkazy DML, na které se vztahují. skutečné množství režie bude záviset na povaze spouštěče, ale jak se všechny spouštěče MySQL provádějí PRO KAŽDOU ROW ---, režie se může rychle akumulovat pro příkazy, které zpracovávají velké množství řádků. Proto byste se měli vyvarovat umisťování drahých příkazů SQL nebo procedurálního kódu do spouštěčů.

Rozšířené vysvětlení režijních nákladů je uvedeno na stranách 529-531. Závěrečný bod z této části uvádí následující:

Lekce je následující: protože spouštěcí kód se spustí jednou pro každý řádek ovlivněný příkazem DML, může se spouštěč snadno stát nejvýznamnějším faktorem ve výkonu DML. Kód uvnitř těla spouště musí být co nejlehčí a zejména pokud je to možné, měly by být všechny příkazy SQL ve spouštěči podporovány indexy.

Vysvětlil jsem další ošklivé aspekty Triggerse v dřívějším příspěvku.

[~ # ~] shrnutí [~ # ~]

Já bych důrazně doporučuji nevyvolávat žádné uložené procedury z Triggeru , i když to MySQL umožňuje. Měli byste si přehrát zkontrolovat aktuální omezení pro MySQL 5.5 .

24
RolandoMySQLDBA

Pokud se jedná o chybu syntaxe, s největší pravděpodobností jste zapomněli změnit oddělovač (stejně jako u uložené procedury). Takže to potřebujete

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

Vypadá to, že čárka za AC je syntaktická chyba:

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