Un déclencheur est une commande SQL prédéfinie qui est automatiquement exécutée lorsque des actions spécifiques se produisent dans la base de données. Il peut être déclenché avant ou après un INSERT
, UPDATE
, ou DELETE
événement.
Les déclencheurs sont principalement utilisés pour maintenir la logique logicielle dans le serveur MySQL, et ils présentent plusieurs avantages :
-
Les déclencheurs permettent de centraliser les opérations mondiales en un seul endroit.
-
Ils réduisent le code côté client et aident à minimiser les allers-retours vers le serveur de base de données.
-
Ils contribuent à rendre les applications plus évolutives sur différentes plates-formes.
Certains cas d'utilisation courants des déclencheurs incluent la journalisation d'audit, le pré-calcul des valeurs de base de données (par exemple, les sommes cumulées) et l'application de règles complexes d'intégrité et de validation des données.
Dans ce guide, vous apprendrez :
-
Comment est structurée la syntaxe d'un déclencheur.
-
Comment créer des déclencheurs qui sont exécutés avant que d'autres événements de base de données ne se produisent.
-
Comment créer des déclencheurs qui sont exécutés après que d'autres événements de base de données se produisent.
-
Comment supprimer des déclencheurs.
Avant de commencer
-
Si vous ne l'avez pas déjà fait, créez un compte Linode et une instance de calcul. Consultez nos guides Premiers pas avec Linode et Création d'une instance de calcul.
-
Suivez notre guide Configuration et sécurisation d'une instance de calcul pour mettre à jour votre système. Vous pouvez également définir le fuseau horaire, configurer votre nom d'hôte, créer un compte utilisateur limité et renforcer l'accès SSH.
-
Un serveur et un client MySQL installés sur le serveur Linode. Des guides d'installation pour MySQL sont disponibles pour différentes distributions dans notre section MySQL.
Préparer la base de données
Pour mieux comprendre le fonctionnement des déclencheurs, nous allons créer un exemple de base de données et y ajouter des exemples de données. Plus tard, nous créerons différents déclencheurs sur la base de données comme exercice de preuve de concept.
-
Tout d'abord, connectez-vous à votre serveur MySQL :
mysql -u root -p
Ensuite, entrez le mot de passe root de votre serveur MySQL et appuyez sur Entrée pour continuer.
-
Ensuite, vous verrez une invite MySQL similaire à celle illustrée ci-dessous :
mysql >
-
Créer une
test_database
en exécutant la commande ci-dessous :CREATE DATABASE test_database;
Sortie :
Query OK, 1 row affected (0.02 sec)
-
Passer à la base de données :
USE test_database;
Sortie :
Database changed
-
Une fois la base de données sélectionnée, nous allons créer des tables que nous utiliserons pour démontrer les déclencheurs. Nous allons commencer par créer les
stores
table. Ce tableau contiendra des informations sur deux exemples de magasins/bureaux à partir desquels notre activité hypothétique opère :CREATE TABLE stores ( store_id BIGINT PRIMARY KEY AUTO_INCREMENT, store_name VARCHAR(50) ) ENGINE=InnoDB;
Sortie :
Query OK, 0 rows affected (0.07 sec)
-
Ensuite, ajoutez deux enregistrements aux
stores
table en exécutant les commandes ci-dessous :INSERT INTO stores (store_name) VALUES ('Philadelphia'); INSERT INTO stores (store_name) VALUES ('Galloway');
Après chaque commande, vous obtiendrez le résultat ci-dessous :
Query OK, 1 row affected (0.08 sec) ...
-
Confirmez les enregistrements en exécutant la commande ci-dessous :
SELECT * FROM stores;
Sortie :
+----------+--------------+ | store_id | store_name | +----------+--------------+ | 1 | Philadelphia | | 2 | Galloway | +----------+--------------+ 2 rows in set (0.01 sec)
-
Ensuite, créez les
products
table. La table contiendra différents produits proposés dans le magasin :CREATE TABLE products ( product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(40), cost_price DOUBLE, retail_price DOUBLE, availability VARCHAR(5) ) ENGINE=InnoDB;
Sortie :
Query OK, 0 rows affected (0.13 sec)
-
Chaque produit sera identifié de manière unique par un
product_id
. -
Un
product_name
champ précisera les noms des éléments. -
Le
cost_price
etretail_price
détermineront respectivement le prix d'achat et de vente. -
Une
availability
définira la disponibilité du produit dans les différents magasins. Si le produit n'est disponible que dans notre magasin local (Philadelphie), nous l'indiquerons avec unLOCAL
valeur. Sinon, nous utiliserons la valeur deALL
pour signifier un produit qui est disponible dans les deux magasins (Philadelphie et Galloway).
-
-
Ajouter des exemples de données aux
products
tableau :INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('WIRELESS MOUSE', '18.23', '30.25','ALL'); INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('8 MP CAMERA', '60.40', '85.40','ALL'); INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('SMART WATCH', '189.60', '225.30','LOCAL');
Vous obtiendrez la sortie ci-dessous après chaque commande d'insertion :
Query OK, 1 row affected (0.02 sec) ...
-
Confirmez si les produits ont été insérés en exécutant la commande ci-dessous :
SELECT * FROM products;
Sortie :
+------------+----------------+------------+--------------+--------------+ | product_id | product_name | cost_price | retail_price | availability | +------------+----------------+------------+--------------+--------------+ | 1 | WIRELESS MOUSE | 18.23 | 30.25 | ALL | | 2 | 8 MP CAMERA | 60.4 | 85.4 | ALL | | 3 | SMART WATCH | 189.6 | 225.3 | LOCAL | +------------+----------------+------------+--------------+--------------+ 3 rows in set (0.00 sec)
-
Ensuite, la disponibilité des produits sera mappée à une autre table nommée
products_to_stores
. Ce tableau référencera simplement leproduct_id
à partir desproducts
table et lestore_id
dans lesstores
tableau où l'article est disponible.Créez le
products_to_stores
table en exécutant le code ci-dessous :CREATE TABLE products_to_stores ( ref_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_id BIGINT, store_id BIGINT ) ENGINE=InnoDB;
Sortie :
Query OK, 0 rows affected (0.14 sec)
-
Ensuite, nous allons créer un
archived_products
table. Le tableau contiendra des informations sur les produits supprimés pour référence future :CREATE TABLE archived_products ( product_id BIGINT PRIMARY KEY , product_name VARCHAR(40), cost_price DOUBLE, retail_price DOUBLE, availability VARCHAR(5) ) ENGINE=InnoDB;
Sortie :
Query OK, 0 rows affected (0.14 sec)
-
Enfin, nous allons créer un
products_price_history
tableau permettant de suivre les différents prix de chaque produit dans le temps :CREATE TABLE products_price_history ( product_id BIGINT PRIMARY KEY AUTO_INCREMENT, price_date DATETIME, retail_price DOUBLE ) ENGINE=InnoDB;
Sortie :
Query OK, 0 rows affected (0.14 sec)
Une fois notre structure de base de données en place, nous pouvons maintenant continuer et apprendre la syntaxe de base d'un déclencheur de base de données MySQL afin de créer notre premier exemple.
Syntaxe du déclencheur
Comme indiqué précédemment, les déclencheurs sont déclenchés automatiquement avant ou après l'exécution d'une commande SQL dans la base de données. La syntaxe de base pour créer des déclencheurs est la suivante :
CREATE TRIGGER TRIGGER_NAME
TRIGGER_TIME TRIGGER_EVENT
ON TABLE_NAME FOR EACH ROW
[TRIGGER BODY];
-
TRIGGER_NAME
:Chaque déclencheur doit avoir un nom unique et vous devez le définir ici. -
TRIGGER_TIME
:SoitBEFORE
ouAFTER
. -
TRIGGER_EVENT
:Vous devez spécifier l'événement de base de données qui invoquera le déclencheur :INSERT
,UPDATE
, ouDELETE
. -
TRIGGER BODY
:Cela spécifie la ou les commandes SQL réelles que vous souhaitez exécuter par votre déclencheur.
Si un corps de déclencheur a plus d'une instruction SQL, vous devez l'inclure dans un BEGIN...END
bloc. De plus, vous devrez modifier temporairement le DELIMITER
qui signale la fin du corps du déclencheur à une nouvelle valeur. Cela garantit que les instructions contenues dans le corps ne sont pas interprétées prématurément par votre client MySQL. Un exemple de ceci ressemble à ce qui suit :
DELIMITER &&
CREATE TRIGGER TRIGGER_NAME
TRIGGER_TIME TRIGGER_EVENT
ON TABLE_NAME FOR EACH ROW
BEGIN
[TRIGGER BODY]
END &&
DELIMITER ;
Remarque La dernière ligne de cet exemple modifie leDELIMITER
retour au;
valeur.
Création de déclencheurs avant événement
Dans cette section, nous examinerons les différents types de déclencheurs qui sont déclenchés avant une opération de base de données. Ceux-ci incluent le BEFORE INSERT
, BEFORE UPDATE
, et BEFORE DELETE
déclencheurs.
Création d'un déclencheur avant insertion
Nous allons créer notre premier BEFORE INSERT
gâchette. Le déclencheur s'assurera que le prix de vente d'un produit est supérieur au prix de revient chaque fois que des articles sont insérés dans les products
table. Sinon, l'utilisateur de la base de données obtiendra une erreur.
-
Toujours sur le
mysql >
invite, entrez la commande ci-dessous :DELIMITER $$ CREATE TRIGGER price_validator BEFORE INSERT ON products FOR EACH ROW IF NEW.cost_price>=NEW.retail_price THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Retail price must be greater than cost price.'; END IF $$ DELIMITER ;
-
Le code ci-dessus définit le nom du déclencheur (
price_validator
), heure (BEFORE
), événement (INSERT
), et le tableau (products
) à affecter. -
Notre déclencheur utilise le
NEW
mot-clé pour vérifier lecost_price
etretail_price
avant qu'un enregistrement ne soit inséré dans lesproducts
table, en utilisant leIF...THEN...END IF
déclaration. -
Si le
cost_price
est supérieur ou égal auretail price
, nos déclencheurs indiquent à MySQL de lever une exception personnalisée demandant à l'utilisateur de rectifier l'erreur.
-
-
Pour tester le déclencheur ci-dessus, essayez d'insérer un produit qui enfreint la règle de validation :
INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('GAMING MOUSE PAD', '145.00', '144.00','LOCAL');
Sortie :
ERROR 1644 (45000): Retail price must be greater than cost price.
Les commandes d'insertion ci-dessus doivent échouer car le
retail_price
(144,00) n'est pas supérieur aucost_price
(145.00).
Création d'un déclencheur avant mise à jour
Ensuite, nous allons créer un BEFORE UPDATE
gâchette. Ce déclencheur empêchera les utilisateurs de la base de données de modifier un nom de produit une fois qu'un produit a été inséré dans la base de données. Si plusieurs utilisateurs travaillent dans la base de données, un BEFORE UPDATE
Le déclencheur peut être utilisé pour rendre les valeurs en lecture seule, ce qui peut empêcher les utilisateurs malveillants ou négligents de modifier inutilement les enregistrements.
-
Créez un nouveau
product_name_validator
déclencheur avec la commande ci-dessous :DELIMITER $$ CREATE TRIGGER product_name_validator BEFORE UPDATE ON products FOR EACH ROW IF NEW.product_name<>OLD.product_name THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product name is read-only and it can not be changed.'; END IF $$ DELIMITER ;
Ce déclencheur compare les valeurs du nouveau
product_name
(NEW.product_name
) et l'ancien nom déjà dans la base de données (OLD.product_name
). S'il y a une non-concordance, une exception est levée. -
Pour appeler le
product_name_validator
déclencheur, nous pouvons tenter de mettre à jour le nom du produit avec l'ID1
:UPDATE products SET product_name='WIRELESS BLUETOOTH MOUSE' WHERE product_id='1';
Sortie :
ERROR 1644 (45000): Product name is read-only and it can not be changed.
Définir un déclencheur avant suppression
Dans cette section, vous verrez comment définir un BEFORE DELETE
déclencheur pour empêcher les utilisateurs de supprimer des enregistrements spécifiques d'une table.
-
Pour créer le
prevent_delete
déclencheur, exécutez la commande ci-dessous :DELIMITER $$ CREATE TRIGGER prevent_delete BEFORE DELETE ON products FOR EACH ROW IF OLD.availability='ALL' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The product can not be deleted because it is available in ALL stores.'; END IF $$ DELIMITER ;
Ce déclencheur empêchera les produits marqués avec une valeur de
ALL
dans la colonne de disponibilité d'être supprimé. -
Ensuite, essayez de supprimer le premier produit de la table des produits et voyez si le déclencheur sera appelé :
DELETE FROM products WHERE product_id='1';
Sortie :
ERROR 1644 (45000): The product can not be deleted because it is available in ALL stores.
Nous avons examiné les différents déclencheurs invoqués avant une opération de base de données. Ensuite, nous examinerons les autres types de déclencheurs déclenchés après des événements de base de données.
Création de déclencheurs après événement
Dans un environnement de production, vous souhaiterez peut-être que certains déclencheurs soient automatiquement exécutés après qu'un événement de base de données se produit (par exemple, insertion d'enregistrements dans différentes tables). Les exemples ci-dessous montrent comment ces types de déclencheurs peuvent être utilisés dans notre exemple de base de données.
Création d'un déclencheur après insertion
Cet exemple crée un déclencheur nommé product_availability
qui insère des enregistrements de mappage dans le products_to_stores
table. Ce déclencheur est utilisé pour appliquer la logique métier ; il permet notamment de définir la disponibilité des produits pour les différents magasins.
-
Exécutez le code ci-dessous pour créer le
product_availability
gâchette. Comme nous avons plusieurs lignes de code dans le corps du déclencheur, nous utiliserons unBEGIN...END
bloquer :DELIMITER $$ CREATE TRIGGER product_availability AFTER INSERT ON products FOR EACH ROW BEGIN IF NEW.availability='LOCAL' then INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '1'); ELSE INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '1'); INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '2'); END IF; END $$ DELIMITER ;
-
Lorsqu'un article est inséré dans les
products
table, le déclencheur vérifiera laavailability
champ. -
S'il est marqué avec le
LOCAL
valeur, le produit sera disponible dans un seul magasin. -
Toute autre valeur indiquera au déclencheur de rendre le produit disponible pour les deux magasins que nous avons créés précédemment.
-
-
Pour voir la
product_availability
déclencheur en action, insérez les deux enregistrements dans la table des produits :INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('BLUETOOTH KEYBOARD', '17.60', '23.30','LOCAL'); INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('DVB-T2 RECEIVE', '49.80', '53.40','ALL');
-
Ensuite, interrogez les
products_to_stores
tableau :SELECT * FROM products_to_stores;
Vous devriez voir une sortie similaire à celle illustrée ci-dessous :
+--------+------------+----------+ | ref_id | product_id | store_id | +--------+------------+----------+ | 1 | 4 | 1 | | 2 | 5 | 1 | | 3 | 5 | 2 | +--------+------------+----------+ 3 rows in set (0.00 sec)
Définir un déclencheur après mise à jour
Un déclencheur peut également être déclenché après un UPDATE
un événement. Nous verrons comment tirer parti de ce type de déclencheur pour suivre l'évolution des prix dans notre magasin au fil du temps.
-
Créer un
product_history_updater
déclencheur en exécutant la commande ci-dessous :CREATE TRIGGER product_history_updater AFTER UPDATE ON products FOR EACH ROW INSERT INTO products_price_history (product_id, price_date, retail_price) VALUES (OLD.product_id, NOW(), NEW.retail_price);
Ce déclencheur enregistre les modifications apportées au
retail_price
d'un produit dans leproducts_price_history
tableau.Remarque Contrairement aux exemples précédents, ce déclencheur n'a qu'une seule instruction dans le corps du déclencheur, nous n'avons donc pas besoin de modifier le
DELIMITER
. -
Ensuite, essayez de mettre à jour le prix du premier produit en exécutant la commande ci-dessous :
UPDATE products SET retail_price='36.75' WHERE product_id='1';
-
Ensuite, interrogez le
products_price_history
tableau pour voir si le changement de prix a été enregistré :SELECT * FROM products_price_history;
Si le déclencheur a fonctionné comme prévu, vous devriez obtenir le résultat ci-dessous :
+------------+---------------------+--------------+ | product_id | price_date | retail_price | +------------+---------------------+--------------+ | 1 | 2020-01-28 11:46:21 | 36.75 | +------------+---------------------+--------------+ 1 row in set (0.00 sec)
Création d'un déclencheur après suppression
Dans certains cas, vous souhaiterez peut-être consigner les opérations de suppression après qu'une action spécifique s'est produite dans la base de données. Vous pouvez y parvenir en utilisant le AFTER DELETE
déclencheur.
-
Créez un nouveau
product_archiver
déclencheur avec la commande ci-dessous :CREATE TRIGGER product_archiver AFTER DELETE ON products FOR EACH ROW INSERT INTO archived_products (product_id, product_name, cost_price, retail_price, availability) VALUES (OLD.product_id, OLD.product_name, OLD.cost_price, OLD.retail_price, OLD.availability);
Ce déclencheur archive les produits supprimés dans une table distincte nommée
archived_products
. Lorsqu'un article est supprimé desproducts
principaux table, notre déclencheur l'enregistrera automatiquement dansarchived_products
tableau pour référence future. -
Ensuite, supprimez un produit de la liste
products
table et voyez si le déclencheur sera appelé :DELETE FROM products WHERE product_id='3';
-
Maintenant, si vous cochez la case
archived_products
table, vous devriez voir un enregistrement :SELECT * FROM archived_products;
Sortie :
+------------+--------------+------------+--------------+--------------+ | product_id | product_name | cost_price | retail_price | availability | +------------+--------------+------------+--------------+--------------+ | 3 | SMART WATCH | 189.6 | 225.3 | LOCAL | +------------+--------------+------------+--------------+--------------+ 1 row in set (0.00 sec)
Supprimer un déclencheur
Vous avez vu les différents types de déclencheurs et comment ils peuvent être utilisés dans un environnement de production. Parfois, vous souhaiterez peut-être supprimer un déclencheur de la base de données.
Vous pouvez supprimer un déclencheur si vous ne souhaitez plus l'utiliser en utilisant la syntaxe ci-dessous :
DROP TRIGGER IF EXISTS TRIGGER_NAME;
Remarque Le IF EXISTS
Le mot-clé est un paramètre facultatif qui ne supprime un déclencheur que s'il existe.
Par exemple, pour supprimer le product_archiving
déclencheur que nous avons défini ci-dessus, utilisez la commande ci-dessous :
DROP TRIGGER IF EXISTS product_archiver;
Sortie :
Query OK, 0 rows affected (0.00 sec)
Attention Soyez prudent lorsque vous supprimez des tables associées à des déclencheurs. Une fois qu'une table est supprimée de la base de données MySQL, les déclencheurs associés sont également automatiquement supprimés.
Plus d'informations
Vous pouvez consulter les ressources suivantes pour plus d'informations sur ce sujet. Bien que ceux-ci soient fournis dans l'espoir qu'ils seront utiles, veuillez noter que nous ne pouvons pas garantir l'exactitude ou l'actualité des documents hébergés en externe.
- Syntaxe de déclencheur MySQL et exemples