Во-первых, получение некоторых синтаксических ошибок из нашей первоначальной попытки:
- Вместо
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 ;
ДБ Fiddle Demo 1 : Попытка удалить больше, чем строку.
DELETE FROM `test` WHERE `id`< 5;
Результат:
Ошибка запроса: ошибка: ER_SIGNAL_EXCEPTION: невозможно удалить более одного
заказ за раз!
ДБ Fiddle Demo 2 : Попытка удалить только одну строку
Запрос № 1
DELETE FROM `test` WHERE `id` = 1;
Удаление успешно произошло. Мы можем проверить оставшиеся строки, используя Select
.
Запрос № 2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |