For det første, at få nogle syntaksfejl ud af vejen fra dit oprindelige forsøg:
- I stedet for
FOR EACH STATEMENT
, skal det væreFOR EACH ROW
. - Da du allerede har defineret afgrænseren til
//
; du skal bruge//
(i stedet for;
) iDROP TRIGGER IF EXISTS ..
erklæring. Row_Count()
vil have 0-værdi i enBefore Delete Trigger
, da ingen rækker er blevet opdateret endnu. Så denne tilgang vil ikke fungere.
Nu er tricket her at bruge Sessionsniveau tilgængelig (og vedvarende) brugerdefinerede variabler
. Vi kan definere en variabel, lad os sige @rows_being_deleted
, og senere kontrollere, om det allerede er defineret eller ej.
For Each Row
kører det samme sæt sætninger for hver række der bliver slettet . Så vi vil bare kontrollere, om sessionsvariablen allerede eksisterer eller ej. Hvis det ikke gør det, kan vi definere det. Så dybest set, for den første række (ved at blive slettet), vil den blive defineret, hvilket vil vare ved, så længe sessionen er der.
Hvis der nu er flere rækker, der skal slettes, vil Trigger køre det samme sæt sætninger for de resterende rækker. I den anden række ville den tidligere definerede variabel blive fundet nu, og vi kan simpelthen smide en undtagelse nu.
Bemærk at der er en chance for, at flere delete-sætninger kan blive udløst inden for samme session. Så før vi kaster undtagelsen, skal vi indstille @rows_being_deleted
værdi tilbage til null
.
Følgende vil virke:
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 :Forsøger at slette mere end række.
DELETE FROM `test` WHERE `id`< 5;
Resultat:
DB Fiddle Demo 2 :Forsøger kun at slette én række
Forespørgsel #1
DELETE FROM `test` WHERE `id` = 1;
Forespørgsel #2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |