Chapitre 20 Déclencheurs

Table des matières

20.1 Syntaxe de CREATE TRIGGER
20.2 Syntaxe de DROP TRIGGER
20.3 Utiliser les déclencheurs

Le support rudimentaire des déclencheurs (triggers) est inclus dans les versions de MySQL à partir de la version 5.0.2. Un déclencheur est un objet de base de données nommé, qui est associé à une table et qui s'active lorsqu'un événement particulier survient dans une table. Par exemple, les commandes suivantes configurent uen table, ainsi qu'un déclencheur pour les commandes INSERT sur cette table. Le déclencheur va effectuer la somme des valeurs insérées dans une des colonnes :

mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
    -> FOR EACH ROW SET @sum = @sum + NEW.amount;

Ce chapitre décrit la syntaxe pour créer et détruire des déclencheurs, et quelques exemples pour les utiliser.

20.1 Syntaxe de CREATE TRIGGER

CREATE TRIGGER trigger_name trigger_time trigger_event
    ON tbl_name FOR EACH ROW trigger_stmt

Un déclencheur est un objet de base de données associé à une table, qui s'active lorsqu'un événement particulier survient.

Le déclencheur est associé à la table appelée tbl_name. tbl_name doit faire référence à une table permanente. Vous ne pouvez pas associer un déclencheur avec une table TEMPORARY ou une vue.

trigger_time est le moment d'action du déclencheur. Il peut être BEFORE (avant) ou AFTER (après), pour indiquer que le délencheur s'active avant ou après la commande qui le déclenche.

trigger_event indique le type de commande qui active le déclencheur. Il peut valoir INSERT, UPDATE ou DELETE. Par exemple, un déclencheur BEFORE pour une commande INSERT peut être utilisé pour vérifier les valeurs avant leur insertion dans la table.

Il ne peut pas y avoir deux déclencheurs pour une même table avec les mêmes configurations de moment et de commande. Par exemple, vous ne pouvez pas avor deux déclencheurs BEFORE UPDATE pour la même table. Mais vous pouvez avoir un déclencheur BEFORE UPDATE et un déclencheur BEFORE INSERT, ou un déclencheur BEFORE UPDATE et un déclencheur AFTER UPDATE.

trigger_stmt est la commande a exécuter lorsque le déclencheur s'active. Si vous voulez utiliser plusieurs commandes, utilisez les agrégateurs BEGIN ... END. Cela vous permet aussi d'utiliser les mêmes codes que ceux utilisés dans des procédures stockées. See Section 19.2.7, « La commande composée BEGIN ... END ».

Note : actuellement, les déclencheurs ont les mêmes limitations que les procédures stockées : ils ne peuvent pas contenir de références directes aux tables via leur nom. Cette limitation sera levée dès que possible.

Cependant, dans la commande d'activation d'un déclencheur, vous pouvez faire référence aux colonnes dan la table associée au déclencheur en utilisant les mots OLD et NEW. OLD.col_name faire référence à une colonne d'une ligne existante avant sa modification ou son effacement. NEW.col_name faire référence à une colonne d'une ligne après insertion ou modification.

L'utilisation de SET NEW.col_name = value requiert le droit de UPDATE sur la colonne. L'utilisation de SET value = NEW.col_name requiert le droit de SELECT sur la colonne.

La commande CREATE TRIGGER requiert le droit de SUPER. Elle a été ajoutée en MySQL 5.0.2.

20.2 Syntaxe de DROP TRIGGER

DROP TRIGGER tbl_name.trigger_name

Supprime un déclencheur. Le nom du déclencheur doit inclure le nom de la table, car chaque déclencheur est associé à une table particulière.

La commande DROP TRIGGER requiert le droit de SUPER. Il a été ajouté en MySQL 5.0.2.

20.3 Utiliser les déclencheurs

Le support des déclencheurs (aussi appelés trigger) a commencé avec MySQL 5.0.2. Actuellement, le support des déclencheurs est rudimentaire, et il y existe des limitations dans les fonctionnalités. Cette section présente comment utiliser les déclencheurs et quelles sont leurs limitations actuelles.

Un déclencheur est une objet de base de données qui est associé à une table, et qui s'active lorsqu'un événement spécifié survient dans la table. Il est possible d'utiliser les déclencheurs pour effectuer des vérifications de valeurs avant insertion, ou pour effectuer des calculs de macrodonnées après une modifications d'une table.

Un déclencheur est associé à une table, et est défini pour s'activer lorsqu'une commande INSERT, DELETE ou UPDATE s'exécute sur la table. Un déclencheur peut être configuré pour s'activer avant ou après l'événement. Par exemple, déclencheur peut être appelé avant que la ligne soit effacée ou modifié dans la table.

Pour créer un déclencheur ou l'effacer, utilisez les commandes CREATE TRIGGER ou DROP TRIGGER. La syntaxe de ces commandes est décrite dans les sections Section 20.1, « Syntaxe de CREATE TRIGGER » et Section 20.2, « Syntaxe de DROP TRIGGER ».

Voici un exemple simple qui associe un déclencheur avec une table pour les commandes INSERT. Il sert d'accumulateur des sommes insérées dans une des colonnes de la table.

La commande suivante crée la table et le déclencheur :

mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
    -> FOR EACH ROW SET @sum = @sum + NEW.amount;

La commande CREATE TRIGGER crée un déclencheur appelé ins_sum qui est associé avec la table account. Il inclut aussi des clauses pour spécifier le moment d'activation, l'événement et l'action du déclencheur :

  • Le mot réservé BEFORE (avant, en anglais) indique le moment d'activation. Dans ce cas, le déclencheur sera activé avant l'insertion des lignes dans la table. L'autre mot réservé est AFTER (Après, en anglais).

  • Le mot réservé INSERT indique l'événement qui active le déclencheur. Dans l'exemple, le déclencheur s'active lors des commandes INSERT. Vous pouvez créer des déclencheur pour les commandes DELETE et UPDATE.

  • La commande qui suit le mot clé FOR EACH ROW définit la commande à exécuter à chaque fois que le déclencheur s'active, ce qui arrive à dès qu'une ligne est insérée. Dans l'exemple, la commande du déclencheur est un simple SET qui accumule la somme des valeurs insérées dans les colonnes amount. La commande utiliser la valeur de la colonne avec la syntaxe NEW.amount (en anglais, nouvelle.montant) ce qui signifie ``la valeur de la colonne amount qui va être insérée''.

Pour utiliser le déclencheur, initialisé l'accumulateur à zéro, puis exécutez une commande INSERT et voyez la valeur finale de l'accumulateur :

mysql> SET @sum = 0;
mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql> SELECT @sum AS 'Total amount inserted';
+-----------------------+
| Total amount inserted |
+-----------------------+
| 1852.48               |
+-----------------------+

Dans ce cas, la valeur de @sum après la commande INSERT est 14.98 + 1937.50 - 100 soit 1852.48.

Pour détruire un déclencheur, utilisez la commande DROP TRIGGER. Le nom du déclencheur doit inclure le nom de la table :

mysql> DROP TRIGGER account.ins_sum;

Comme le déclencheur est associé avec une table, vous ne pouvez pas avoir plusieurs déclencheurs sur une même table qui portent le même nom. Soyez aussi conscients que l'espace de noms des déclencheurs risque de changer à l'avenir. C'est à dire que l'unicité des noms de déclencheurs par table risque d'être étendu à l'unicité de déclencheurs au niveau du serveur. Pour faciliter la compatibilité ascendante, essayez d'utiliser des noms de déclencheurs qui soient uniques dans toute la base.

En plus du fait que les noms de déclencheurs doivent être uniques pour une table, il y a d'autres limitations sur le type de déclencheurs que vous pouvez mettre en place. En particulier, vous ne pouvez pas avoir deux déclencheurs qui ont le même moment d'activation et le même événement d'activation. Par exemple, vous ne pouvez pas définir deux déclencheurs BEFORE INSERT et deux déclencheurs AFTER UPDATE pour la même table. Ce n'est probablement pas une limitation importate, car il est possible de définir un déclencheur qui exécute plusieurs commandes en utilisant une commande complexe, encadrée par les mots BEGIN … END, après le mot clé FOR EACH ROW. Un exemple vous est présenté ultérieurement dans cette section.

Il y a aussi des limitations dans ce qui peut apparaître dans la commande que le déclencheur peut éxecuter lorsqu'il est activé :

  • Le déclencheur ne peut pas faire référence directe aux tables par leur nom, y compris la table à laquelle il est associé. Par contre, vous pouvez utiliser les mots clés OLD (ancien en anglais) et NEW (nouveau en anglais). OLD fait référence à la ligne existante avant la modification ou l'effacement. NEW faire référence à la nouvelle ligne insérée ou à la ligne modifiée.

  • Le déclencheur ne peut pas exécuter de procédures avec la commande CALL. Cela signifie que vous ne pouvez pas contourner le problèmes des noms de tables en appelant une procédure stockée qui utilise les noms de tables.

  • Le déclencheur ne peut pas utiliser de commande qui ouvre ou ferme une transaction avec START TRANSACTION, COMMIT ou ROLLBACK.

Les mots clé OLD et NEW vous permette d'accéder aux colonnes dans les lignes affectées par le déclencheur. OLD et NEW ne sont pas sensibles à la casse. Dans un déclencheur INSERT, seul NEW.col_name peut être utilisée : il n'y a pas d'ancienne ligne. Dans un déclencheur DELETE, seul la valeur OLD.col_name peut être utilisée : il n'y a pas de nouvelle ligne. Dans un déclencheur UPDATE, vous pouvez utiliser OLD.col_name pour faire référence aux colonnes dans leur état avant la modification, et NEW.col_name pour faire référence à la valeur après la modification.

Une colonne identifiée par OLD est en lecture seule. Vous pouvez lire sa valeur mais vous ne pouvez pas la modifier. Une colonne identifiée avec la valeur NEW peut être lue si vous avez les droits de SELECT dessus. Dans un déclencheur BEFORE, vous pouvez aussi changer la valeur avec la commande SET NEW.col_name = value si vous avez les droits de UPDATE. Cela signifie que vous pouvez utiliser un déclencheur pour modifier les valeurs insérées dans une nouvelle ligne ou les valeurs modifiées.

Dans un déclencheur BEFORE, la valeur NEW d'une colonne AUTO_INCREMENT vaut 0, et non pas le nombre séquentiel automatiquement généré car ce nombre sera généré lorsque la ligne sera réellement insérée.

OLD et NEW sont des extensions de MySQL aux déclencheurs.

En utilisant la syntaxe BEGIN … END, vous pouvez définir un déclencheur qui exécute plusieurs commandes. À l'intérieur d'un bloc BEGIN, vous pouvez aussi utiliser les autres syntaxes autorisées dans les routines stockées, telles que les conditions et les boucles. Cependant, tout comme pour les procédures stockées, lorsque vous définissez un déclencheur qui s'exéctue sur plusieurs commandes, il est nécessaire de redéfinir le délimiteur de commande si vous saisissez le déclencheur à l'aide d'un utilisatier en ligne de commande tel que mysql pour que vous puissiez utiliser le caractère ‘;’ à l'intérieur de la définition. L'exemple ci-dessous illustre ces points. Il définit un déclencheur UPDATE qui vérifie la valeur d'une ligne avant sa modification, et s'arrange pour que les valeurs soient dans l'intervalle de 0 à 100. Cela doit être fait avant (BEFORE) la modification, pour que la valeur soit vérifié avant d'être utilisée :

mysql> delimiter //
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account
    -> FOR EACH ROW
    -> BEGIN
    ->     IF NEW.amount < 0 THEN
    ->         SET NEW.amount = 0;
    ->     ELSEIF NEW.amount > 100 THEN
    ->         SET NEW.amount = 100;
    ->     END IF;
    -> END//
mysql> delimiter ;

Il vous viendra surement à l'esprit qu'il serait plus facile de définir une procédure stockée séparément, pour l'invoquer depuis le déclencheur grâce à un simple appel à CALL. Cela serait surement avantageux si vous voulez appeler la même routine depuis plusieurs déclencheurs. Cependant, les déclencheurs ne peuvent pas utiliser la commande CALL. Vous devez absolument réécrire les commandes composées de chaque commande CREATE TRIGGER que vous voulez utiliser.