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 -pEnsuite, 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_databaseen 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
storestable. 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
storestable 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
productstable. 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_namechamp précisera les noms des éléments. -
Le
cost_priceetretail_pricedétermineront respectivement le prix d'achat et de vente. -
Une
availabilitydé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 unLOCALvaleur. Sinon, nous utiliserons la valeur deALLpour signifier un produit qui est disponible dans les deux magasins (Philadelphie et Galloway).
-
-
Ajouter des exemples de données aux
productstableau :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 desproductstable et lestore_iddans lesstorestableau où l'article est disponible.Créez le
products_to_storestable 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_productstable. 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_historytableau 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:SoitBEFOREouAFTER. -
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 leDELIMITERretour 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
NEWmot-clé pour vérifier lecost_priceetretail_priceavant qu'un enregistrement ne soit inséré dans lesproductstable, en utilisant leIF...THEN...END IFdéclaration. -
Si le
cost_priceest 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_validatordé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_validatordé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_deletedé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
ALLdans 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_availabilitygâchette. Comme nous avons plusieurs lignes de code dans le corps du déclencheur, nous utiliserons unBEGIN...ENDbloquer :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
productstable, le déclencheur vérifiera laavailabilitychamp. -
S'il est marqué avec le
LOCALvaleur, 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_availabilitydé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_storestableau :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_updaterdé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_priced'un produit dans leproducts_price_historytableau.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_historytableau 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_archiverdé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é desproductsprincipaux table, notre déclencheur l'enregistrera automatiquement dansarchived_productstableau pour référence future. -
Ensuite, supprimez un produit de la liste
productstable et voyez si le déclencheur sera appelé :DELETE FROM products WHERE product_id='3'; -
Maintenant, si vous cochez la case
archived_productstable, 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