En primer lugar, eliminar algunos errores de sintaxis de su intento original:
- En lugar de
FOR EACH STATEMENT
, debería serFOR EACH ROW
. - Dado que ya ha definido el Delimitador para
//
; necesitas usar//
(en lugar de;
) en elDROP TRIGGER IF EXISTS ..
declaración. Row_Count()
tendrá valor 0 en unBefore Delete Trigger
, ya que aún no se han actualizado filas. Entonces este enfoque no funcionará.
Ahora, el truco aquí es usar accesible (y persistente) a nivel de sesión variables definidas por el usuario
. Podemos definir una variable, digamos @rows_being_deleted
, y luego verifique si ya está definido o no.
For Each Row
ejecuta el mismo conjunto de declaraciones para cada fila que se elimina . Entonces, solo verificaremos si la variable de sesión ya existe o no. Si no es así, podemos definirlo. Básicamente, para la primera fila (que se elimina), se definirá, lo que persistirá mientras la sesión esté allí.
Ahora, si hay más filas para eliminar, Trigger ejecutaría el mismo conjunto de declaraciones para las filas restantes. En la segunda fila, la variable previamente definida se encontraría ahora, y ahora simplemente podemos lanzar una excepción.
Nota que existe la posibilidad de que, dentro de la misma sesión, se activen varias declaraciones de eliminación. Entonces, antes de lanzar una excepción, debemos configurar @rows_being_deleted
valor de nuevo a null
.
Lo siguiente funcionará:
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 Demostración 1 :Intentando eliminar más de una fila.
DELETE FROM `test` WHERE `id`< 5;
Resultado:
DB Fiddle Demostración 2 :Tratando de eliminar solo una fila
Consulta #1
DELETE FROM `test` WHERE `id` = 1;
Consulta #2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |