sql >> Databasteknik >  >> RDS >> Mysql

MySQL Before Delete trigger för att undvika att radera flera rader

För det första, få några syntaxfel ur vägen från ditt ursprungliga försök:

  • Istället för FOR EACH STATEMENT , bör det vara FOR EACH ROW .
  • Eftersom du redan har definierat avgränsaren till //; du måste använda // (istället för ; ) i DROP TRIGGER IF EXISTS .. uttalande.
  • Row_Count() kommer att ha 0 värde i en Before Delete Trigger , eftersom inga rader har uppdaterats ännu. Så det här tillvägagångssättet kommer inte att fungera.

Nu är tricket här att använda tillgänglig (och beständig) på sessionsnivå användardefinierade variabler . Vi kan definiera en variabel, låt oss säga @rows_being_deleted , och senare kontrollera om det redan är definierat eller inte.

For Each Row kör samma uppsättning satser för varje rad som tas bort . Så vi kommer bara att kontrollera om sessionsvariabeln redan finns eller inte. Om det inte gör det kan vi definiera det. Så i princip, för den första raden (som tas bort), kommer den att definieras, vilket kommer att kvarstå så länge sessionen är där.

Om det nu finns fler rader som ska raderas, skulle Trigger köra samma uppsättning satser för de återstående raderna. I den andra raden skulle den tidigare definierade variabeln hittas nu, och vi kan helt enkelt göra ett undantag nu.

Obs att det finns en chans att flera delete-satser kan triggas inom samma session. Så innan vi gör undantag måste vi ställa in @rows_being_deleted värde tillbaka till null .

Följande kommer att fungera:

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 :Försöker ta bort fler än rader.

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

Resultat:

DB Fiddle Demo 2 :Försöker ta bort endast en rad

Fråga #1

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

Fråga #2

SELECT * FROM `test`;

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



  1. Nya Microsoft Access-funktioner på väg!

  2. Massdatakonverteringsfel (typfel överensstämmer eller ogiltigt tecken för angiven teckentabell) för rad 1, kolumn 4 (år)

  3. SQL-uppdateringsfråga med grupp för klausul

  4. Oracle FOR LOOP REVERSE Exempel