För det första, få några syntaxfel ur vägen från ditt ursprungliga försök:
- Istället för
FOR EACH STATEMENT
, bör det varaFOR EACH ROW
. - Eftersom du redan har definierat avgränsaren till
//
; du måste använda//
(istället för;
) iDROP TRIGGER IF EXISTS ..
uttalande. Row_Count()
kommer att ha 0 värde i enBefore Delete Trigger
, eftersom inga rader har uppdaterats ännu. Så det här tillvägagångssättet kommer inte att fungera.
Nu är tricket här att använda tillgänglig (och beständig) på sessionsnivå användardefinierade variabler
. Vi kan definiera en variabel, låt oss säga @rows_being_deleted
, och senare kontrollera om det redan är definierat eller inte.
For Each Row
kör samma uppsättning satser för varje rad som tas bort . Så vi kommer bara att kontrollera om sessionsvariabeln redan finns eller inte. Om det inte gör det kan vi definiera det. Så i princip, för den första raden (som tas bort), kommer den att definieras, vilket kommer att kvarstå så länge sessionen är där.
Om det nu finns fler rader som ska raderas, skulle Trigger köra samma uppsättning satser för de återstående raderna. I den andra raden skulle den tidigare definierade variabeln hittas nu, och vi kan helt enkelt göra ett undantag nu.
Obs att det finns en chans att flera delete-satser kan triggas inom samma session. Så innan vi gör undantag måste vi ställa in @rows_being_deleted
värde tillbaka till null
.
Följande kommer att fungera:
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 :Försöker ta bort fler än rader.
DELETE FROM `test` WHERE `id`< 5;
Resultat:
DB Fiddle Demo 2 :Försöker ta bort endast en rad
Fråga #1
DELETE FROM `test` WHERE `id` = 1;
Fråga #2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |