sql >> Database >  >> RDS >> Mysql

MySQL Before Delete-trigger om te voorkomen dat meerdere rijen worden verwijderd

Ten eerste, enkele syntaxisfout(en) uit de weg ruimen, van uw oorspronkelijke poging:

  • In plaats van FOR EACH STATEMENT , het moet FOR EACH ROW . zijn .
  • Omdat je het scheidingsteken al hebt gedefinieerd voor //; je moet // . gebruiken (in plaats van ; ) in de DROP TRIGGER IF EXISTS .. verklaring.
  • Row_Count() heeft een waarde van 0 in een Before 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   |



  1. Transactielogboeken bekijken in SQL Server 2008

  2. meerdere waarden invoegen van selectievakje alleen laatste waarde neemt in database

  3. Opgeslagen Oracle-procedure:retourneer zowel de resultaatset als de out-parameters

  4. Laatst ingevoegde auto-increment-ID ophalen in mysql