Първо, премахване на някои синтактични грешки от първоначалния ви опит:
- Вместо
FOR EACH STATEMENT
, трябва да еFOR EACH ROW
. - Тъй като вече сте дефинирали разделителя за
//
; трябва да използвате//
(вместо;
) вDROP TRIGGER IF EXISTS ..
изявление. Row_Count()
ще има стойност 0 вBefore Delete Trigger
, тъй като все още няма актуализирани редове. Така че този подход няма да работи.
Сега трикът тук е да използвате Достъпен (и постоянен) на ниво сесия дефинирани от потребителя променливи
. Можем да дефинираме променлива, да кажем @rows_being_deleted
, а по-късно проверете дали вече е дефиниран или не.
For Each Row
изпълнява същия набор от изрази за всеки ред, които се изтрива . Така че просто ще проверим дали променливата на сесията вече съществува или не. Ако не е така, можем да го дефинираме. Така че по принцип за първия ред (който се изтрива), той ще бъде дефиниран, което ще продължи, докато сесията е там.
Сега, ако има повече редове за изтриване, Trigger ще изпълнява същия набор от оператори за останалите редове. Във втория ред сега ще бъде намерена предварително дефинираната променлива и можем просто да хвърлим изключение сега.
Забележка че има вероятност в рамките на една и съща сесия да се задействат множество оператори за изтриване. Така че, преди да хвърлим изключение, трябва да зададем @rows_being_deleted
стойност обратно на null
.
Следното ще работи:
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 1 :Опитвам се да изтрия повече от ред.
DELETE FROM `test` WHERE `id`< 5;
Резултат:
Демонстрация на DB Fiddle 2 :Опитвам се да изтрия само един ред
Запитване №1
DELETE FROM `test` WHERE `id` = 1;
Запитване №2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |