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 |