Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL Before Delete-Trigger, um das Löschen mehrerer Zeilen zu vermeiden

Erstens, einige Syntaxfehler aus Ihrem ursprünglichen Versuch aus dem Weg räumen:

  • Statt FOR EACH STATEMENT , es sollte FOR EACH ROW sein .
  • Da Sie das Trennzeichen bereits auf // definiert haben; Sie müssen // verwenden (statt ; ) im DROP TRIGGER IF EXISTS .. Erklärung.
  • Row_Count() hat den Wert 0 in einem Before Delete Trigger , da noch keine Zeilen aktualisiert wurden. Dieser Ansatz wird also nicht funktionieren.

Der Trick besteht nun darin, Zugänglich (und Persistent) auf Sitzungsebene zu verwenden benutzerdefinierte Variablen . Wir können eine Variable definieren, sagen wir @rows_being_deleted , und prüfen Sie später, ob es bereits definiert ist oder nicht.

For Each Row führt denselben Satz von Anweisungen für jede Zeile aus, die gelöscht wird . Wir werden also nur prüfen, ob die Sitzungsvariable bereits vorhanden ist oder nicht. Wenn nicht, können wir es definieren. Im Grunde wird also die erste Zeile (die gelöscht wird) definiert, die bestehen bleibt, solange die Sitzung besteht.

Wenn nun weitere Zeilen gelöscht werden müssen, würde Trigger denselben Satz von Anweisungen für die verbleibenden Zeilen ausführen. In der zweiten Zeile würde nun die vorher definierte Variable stehen und wir können jetzt einfach eine Exception werfen.

Hinweis dass die Möglichkeit besteht, dass innerhalb derselben Sitzung mehrere Löschanweisungen ausgelöst werden. Bevor wir also eine Ausnahme auslösen, müssen wir @rows_being_deleted festlegen Wert zurück auf null .

Folgendes wird funktionieren:

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 :Es wird versucht, mehr als eine Zeile zu löschen.

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

Ergebnis:

DB Fiddle Demo 2 :Es wird versucht, nur eine Zeile zu löschen

Abfrage 1

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

Abfrage 2

SELECT * FROM `test`;

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