Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL Преди изтриване тригер, за да избегнете изтриване на множество редове

Първо, премахване на някои синтактични грешки от първоначалния ви опит:

  • Вместо FOR EACH STATEMENT , трябва да е FOR EACH ROW .
  • Тъй като вече сте дефинирали разделителя за //; трябва да използвате // (вместо ; ) в DROP TRIGGER IF EXISTS .. изявление.
  • Row_Count() ще има стойност 0 в Before Delete Trigger , тъй като все още няма актуализирани редове. Така че този подход няма да работи.

Сега трикът тук е да използвате Достъпен (и постоянен) на ниво сесия дефинирани от потребителя променливи . Можем да дефинираме променлива, да кажем @rows_being_deleted , а по-късно проверете дали вече е дефиниран или не.

For Each Row изпълнява същия набор от изрази за всеки ред, които се изтрива . Така че просто ще проверим дали променливата на сесията вече съществува или не. Ако не е така, можем да го дефинираме. Така че по принцип за първия ред (който се изтрива), той ще бъде дефиниран, което ще продължи, докато сесията е там.

Сега, ако има повече редове за изтриване, Trigger ще изпълнява същия набор от оператори за останалите редове. Във втория ред сега ще бъде намерена предварително дефинираната променлива и можем просто да хвърлим изключение сега.

Забележка че има вероятност в рамките на една и съща сесия да се задействат множество оператори за изтриване. Така че, преди да хвърлим изключение, трябва да зададем @rows_being_deleted стойност обратно на null .

Следното ще работи:

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 1 :Опитвам се да изтрия повече от ред.

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

Резултат:

Демонстрация на DB Fiddle 2 :Опитвам се да изтрия само един ред

Запитване №1

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

Запитване №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. MYSQL изберете присъединяване към множество таблици и SUM

  2. Left Join превъзхожда Inner Join?

  3. com.mysql.jdbc.PacketTooBigException

  4. Автоматично генериране на диаграма на база данни MySQL

  5. Разлика между float и десетичния тип данни