Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL Before Delete trigger per evitare di eliminare più righe

In primo luogo, eliminando alcuni errori di sintassi dal tuo tentativo originale:

  • Invece di FOR EACH STATEMENT , dovrebbe essere FOR EACH ROW .
  • Dato che hai già definito il Delimitatore su //; devi usare // (invece di ; ) nel DROP TRIGGER IF EXISTS .. dichiarazione.
  • Row_Count() avrà un valore 0 in un Before Delete Trigger , poiché nessuna riga è stata ancora aggiornata. Quindi questo approccio non funzionerà.

Ora, il trucco qui è usare Accessibile (e persistente) a livello di sessione variabili definite dall'utente . Possiamo definire una variabile, diciamo @rows_being_deleted , e successivamente verificare se è già definito o meno.

For Each Row esegue lo stesso insieme di istruzioni per ogni riga eliminata . Quindi, verificheremo semplicemente se la variabile di sessione esiste già o meno. In caso contrario, possiamo definirlo. Quindi, in pratica, per la prima riga (eliminata), verrà definita, che persisterà finché la sessione è presente.

Ora, se ci sono più righe da eliminare, Trigger eseguirà lo stesso set di istruzioni per le righe rimanenti. Nella seconda riga, la variabile definita in precedenza verrebbe trovata ora e ora possiamo semplicemente lanciare un'eccezione.

Nota che esiste la possibilità che all'interno della stessa sessione vengano attivate più istruzioni di eliminazione. Quindi, prima di lanciare un'eccezione, dobbiamo impostare @rows_being_deleted valore torna a null .

Di seguito funzionerà:

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 ;

DB Fiddle Demo 1 :Tentativo di eliminare più di una riga.

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

Risultato:

DB Fiddle Demo 2 :Tentativo di eliminare solo una riga

Richiesta n. 1

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

Richiesta n. 2

SELECT * FROM `test`;

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