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

Déclencheur MySQL Before Delete pour éviter de supprimer plusieurs lignes

Tout d'abord, éliminons les erreurs de syntaxe de votre tentative initiale :

  • Au lieu de FOR EACH STATEMENT , il devrait être FOR EACH ROW .
  • Puisque vous avez déjà défini le délimiteur sur //; vous devez utiliser // (au lieu de ; ) dans le DROP TRIGGER IF EXISTS .. déclaration.
  • Row_Count() aura la valeur 0 dans un Before Delete Trigger , car aucune ligne n'a encore été mise à jour. Cette approche ne fonctionnera donc pas.

Maintenant, l'astuce consiste à utiliser Accessible au niveau de la session (et persistant) variables définies par l'utilisateur . Nous pouvons définir une variable, disons @rows_being_deleted , et vérifiez plus tard s'il est déjà défini ou non.

For Each Row exécute le même ensemble d'instructions pour chaque ligne supprimée . Donc, nous allons juste vérifier si la variable de session existe déjà ou non. Si ce n'est pas le cas, nous pouvons le définir. Donc, fondamentalement, pour la première ligne (en cours de suppression), elle sera définie, qui persistera tant que la session sera là.

Maintenant, s'il y a plus de lignes à supprimer, Trigger exécutera le même ensemble d'instructions pour les lignes restantes. Dans la deuxième ligne, la variable précédemment définie serait trouvée maintenant, et nous pouvons simplement lancer une exception maintenant.

Remarque qu'il est possible qu'au cours de la même session, plusieurs instructions de suppression soient déclenchées. Donc, avant de lancer une exception, nous devons définir le @rows_being_deleted valeur à null .

Ce qui suit fonctionnera :

DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion //
CREATE TRIGGER prevent_multiple_deletion
  BEFORE DELETE ON `test`
  FOR EACH ROW  
    BEGIN

       -- check if the variable is already defined or not
       IF( @rows_being_deleted IS NULL ) THEN 
         SET @rows_being_deleted = 1; -- set its value

       ELSE -- it already exists and we are in next "row"

         -- just for testing to check the row count
         -- SET @rows_being_deleted = @rows_being_deleted + 1;

         -- We have to reset it to null, as within same session
         -- another delete statement may be triggered.
            SET @rows_being_deleted = NULL;

         -- throw exception
         SIGNAL SQLSTATE '45000' 
         SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
       END IF;

  END //

DELIMITER ;

Démo DB Fiddle 1 :Tentative de suppression de plusieurs lignes.

DELETE FROM `test` WHERE `id`< 5;

Résultat :

DB Fiddle Demo 2 :Tentative de suppression d'une seule ligne

Requête 1

DELETE FROM `test` WHERE `id` = 1;

Requête n° 2

SELECT * FROM `test`;

| id  | a   | b   |
| --- | --- | --- |
| 2   | 3   | 4   |