Ten eerste, enkele syntaxisfout(en) uit de weg ruimen, van uw oorspronkelijke poging:
- In plaats van
FOR EACH STATEMENT
, het moetFOR EACH ROW
. zijn . - Omdat je het scheidingsteken al hebt gedefinieerd voor
//
; je moet//
. gebruiken (in plaats van;
) in deDROP TRIGGER IF EXISTS ..
verklaring. Row_Count()
heeft een waarde van 0 in eenBefore Delete Trigger
, aangezien er nog geen rijen zijn bijgewerkt. Deze aanpak zal dus niet werken.
De truc hier is om Toegankelijk (en persistent) op sessieniveau te gebruiken door de gebruiker gedefinieerde variabelen
. We kunnen een variabele definiëren, laten we zeggen @rows_being_deleted
en controleer later of het al is gedefinieerd of niet.
For Each Row
voert dezelfde reeks instructies uit voor elke rij die wordt verwijderd . We zullen dus gewoon controleren of de sessievariabele al bestaat of niet. Als dat niet het geval is, kunnen we het definiëren. Dus eigenlijk wordt de eerste rij (die wordt verwijderd) gedefinieerd, die blijft bestaan zolang de sessie er is.
Als er nu meer rijen moeten worden verwijderd, voert Trigger dezelfde reeks instructies uit voor de resterende rijen. In de tweede rij zou de eerder gedefinieerde variabele nu worden gevonden, en we kunnen nu eenvoudig een uitzondering maken.
Opmerking dat er een kans is dat binnen dezelfde sessie meerdere delete-instructies worden geactiveerd. Dus voordat we een uitzondering maken, moeten we de @rows_being_deleted
. instellen waarde terug naar null
.
Het volgende werkt:
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 :probeert meer dan rij te verwijderen.
DELETE FROM `test` WHERE `id`< 5;
Resultaat:
DB Fiddle Demo 2 :probeert slechts één rij te verwijderen
Vraag #1
DELETE FROM `test` WHERE `id` = 1;
Vraag #2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |