In primo luogo, eliminando alcuni errori di sintassi dal tuo tentativo originale:
- Invece di
FOR EACH STATEMENT
, dovrebbe essereFOR EACH ROW
. - Dato che hai già definito il Delimitatore su
//
; devi usare//
(invece di;
) nelDROP TRIGGER IF EXISTS ..
dichiarazione. Row_Count()
avrà un valore 0 in unBefore 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 |