Za prvé, odstranění některých syntaktických chyb z vašeho původního pokusu:
- Místo
FOR EACH STATEMENT
, mělo by to býtFOR EACH ROW
. - Protože jste již definovali oddělovač na
//
; musíte použít//
(místo;
) vDROP TRIGGER IF EXISTS ..
prohlášení. Row_Count()
bude mít hodnotu 0 vBefore Delete Trigger
, protože ještě nebyly aktualizovány žádné řádky. Tento přístup tedy nebude fungovat.
Nyní je trik v použití Dostupné (a trvalé) na úrovni relace uživatelsky definované proměnné
. Můžeme definovat proměnnou, řekněme @rows_being_deleted
a později zkontrolujte, zda je již definován nebo ne.
For Each Row
spustí stejnou sadu příkazů pro každý odstraňovaný řádek . Takže jen zkontrolujeme, zda proměnná relace již existuje nebo ne. Pokud tomu tak není, můžeme to definovat. V zásadě se tedy pro první řádek (který se smaže) nadefinuje, což bude přetrvávat, dokud tam bude relace.
Nyní, pokud existuje více řádků k odstranění, Trigger spustí stejnou sadu příkazů pro zbývající řádky. Ve druhém řádku by se nyní nacházela dříve definovaná proměnná a nyní můžeme jednoduše vyvolat výjimku.
Poznámka že existuje šance, že v rámci stejné relace může být spuštěno více příkazů delete. Takže před vyvoláním výjimky musíme nastavit @rows_being_deleted
hodnotu zpět na null
.
Bude fungovat následující:
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 :Pokus o smazání více než řádku.
DELETE FROM `test` WHERE `id`< 5;
Výsledek:
DB Fiddle Demo 2 :Pokus o smazání pouze jednoho řádku
Dotaz č. 1
DELETE FROM `test` WHERE `id` = 1;
Dotaz č. 2
SELECT * FROM `test`;
| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |