Mysql
 sql >> Base de données >  >> RDS >> Mysql

Travailler avec des déclencheurs dans une base de données MySQL - Un tutoriel

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

  1. 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.

  2. 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.

  3. 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.

  1. 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.

  2. Ensuite, vous verrez une invite MySQL similaire à celle illustrée ci-dessous :

    mysql >
  3. 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)
  4. Passer à la base de données :

    USE test_database;
    

    Sortie :

    Database changed
  5. 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)
  6. 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)
    ...
  7. 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)
  8. 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 et retail_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 un LOCAL valeur. Sinon, nous utiliserons la valeur de ALL pour signifier un produit qui est disponible dans les deux magasins (Philadelphie et Galloway).

  9. 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)
    ...
  10. 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)
  11. Ensuite, la disponibilité des produits sera mappée à une autre table nommée products_to_stores . Ce tableau référencera simplement le product_id à partir des products table et le store_id dans les stores 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)
  12. 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)
  13. 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 :Soit BEFORE ou AFTER .

  • TRIGGER_EVENT  :Vous devez spécifier l'événement de base de données qui invoquera le déclencheur :INSERT , UPDATE , ou DELETE .

  • 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 le DELIMITER 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.

  1. 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 le cost_price et retail_price avant qu'un enregistrement ne soit inséré dans les products table, en utilisant le IF...THEN...END IF déclaration.

    • Si le cost_price est supérieur ou égal au retail price , nos déclencheurs indiquent à MySQL de lever une exception personnalisée demandant à l'utilisateur de rectifier l'erreur.

  2. 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 au cost_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.

  1. 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.

  2. Pour appeler le product_name_validator déclencheur, nous pouvons tenter de mettre à jour le nom du produit avec l'ID 1 :

    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.

  1. 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é.

  2. 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.

  1. 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 un BEGIN...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 la availability 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.

  2. 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');
    
  3. 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.

  1. 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 le products_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 .
  2. 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';
    
  3. 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.

  1. 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é des products principaux table, notre déclencheur l'enregistrera automatiquement dans archived_products tableau pour référence future.

  2. Ensuite, supprimez un produit de la liste products table et voyez si le déclencheur sera appelé :

    DELETE FROM products WHERE product_id='3';
    
  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