Em primeiro lugar, tirando alguns erros de sintaxe do nosso caminho, da sua tentativa original:
- Em vez de
FOR EACH STATEMENT
, deve serFOR EACH ROW
. - Como você já definiu o Delimitador para
//
; você precisa usar//
(em vez de;
) noDROP TRIGGER IF EXISTS ..
declaração. Row_Count()
terá valor 0 em umBefore Delete Trigger
, pois nenhuma linha foi atualizada ainda. Portanto, essa abordagem não funcionará.
Agora, o truque aqui é usar Acessível em nível de sessão (e persistente) variáveis definidas pelo usuário . Podemos definir uma variável, digamos
@rows_being_deleted
, e depois verifique se já está definido ou não. For Each Row
executa o mesmo conjunto de instruções para cada linha sendo excluída . Então, vamos apenas verificar se a variável de sessão já existe ou não. Se não, podemos defini-lo. Então, basicamente, para a primeira linha (sendo excluída), ela será definida, o que persistirá enquanto a sessão estiver lá. Agora, se houver mais linhas a serem excluídas, o Trigger estaria executando o mesmo conjunto de instruções para as linhas restantes. Na segunda linha, a variável definida anteriormente seria encontrada agora, e podemos simplesmente lançar uma exceção agora.
Observação que há uma chance de que, na mesma sessão, várias instruções de exclusão sejam acionadas. Portanto, antes de lançar uma exceção, precisamos definir o
@rows_being_deleted
valor de volta para null
. A seguir 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 Demo 1 :Tentando excluir mais de uma linha.
DELETE FROM `test` WHERE `id`< 5;
Resultado:
DB Fiddle Demo 2 :Tentando excluir apenas uma linha
Consulta nº 1
DELETE FROM `test` WHERE `id` = 1;
Consulta nº 2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |