Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Wyzwalacz MySQL przed usunięciem, aby uniknąć usuwania wielu wierszy

Po pierwsze, usunięcie błędów składniowych z naszej pierwotnej próby:

  • Zamiast FOR EACH STATEMENT , powinno być FOR EACH ROW .
  • Ponieważ już zdefiniowałeś separator jako //; musisz użyć // (zamiast ; ) w DROP TRIGGER IF EXISTS .. oświadczenie.
  • Row_Count() będzie miał wartość 0 w Before Delete Trigger , ponieważ żadne wiersze nie zostały jeszcze zaktualizowane. Więc to podejście nie zadziała.

Teraz sztuczka polega na tym, aby użyć Dostępnych (i trwałych) na poziomie sesji zmienne zdefiniowane przez użytkownika . Możemy zdefiniować zmienną, powiedzmy @rows_being_deleted , a później sprawdź, czy jest już zdefiniowany, czy nie.

For Each Row uruchamia ten sam zestaw instrukcji dla każdego usuniętego wiersza . Więc po prostu sprawdzimy, czy zmienna sesji już istnieje, czy nie. Jeśli tak nie jest, możemy to zdefiniować. Zasadniczo więc dla pierwszego wiersza (usuwanego) zostanie on zdefiniowany, co będzie trwać tak długo, jak długo będzie trwała sesja.

Teraz, jeśli jest więcej wierszy do usunięcia, Trigger uruchomi ten sam zestaw instrukcji dla pozostałych wierszy. W drugim wierszu zostałaby teraz znaleziona wcześniej zdefiniowana zmienna i możemy teraz po prostu rzucić wyjątek.

Uwaga że istnieje szansa, że ​​w ramach tej samej sesji może zostać uruchomionych wiele instrukcji usuwania. Dlatego przed zgłoszeniem wyjątku musimy ustawić @rows_being_deleted wartość z powrotem do null .

Działają następujące:

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 :Próbuję usunąć więcej niż wiersz.

DELETE FROM `test` WHERE `id`< 5;

Wynik:

DB Fiddle Demo 2 :Próba usunięcia tylko jednego wiersza

Zapytanie nr 1

DELETE FROM `test` WHERE `id` = 1;

Zapytanie nr 2

SELECT * FROM `test`;

| id  | a   | b   |
| --- | --- | --- |
| 2   | 3   | 4   |



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy pole tabeli może zawierać myślnik?

  2. Pomoc z zapytaniem SQL, aby znaleźć następny wolny termin dla systemu rezerwacji

  3. „max_user_connections” ustawiono na 200 – nadal pojawia się błąd

  4. Jaka jest różnica między usuwaniem z table_a a obcinaniem tabeli table_a w MySQL?

  5. Używasz LIMIT w GROUP BY, aby uzyskać N wyników na grupę?