sql >> Databáze >  >> RDS >> Mysql

MySQL Before Delete spoušť, aby se zabránilo smazání více řádků

Za prvé, odstranění některých syntaktických chyb z vašeho původního pokusu:

  • Místo FOR EACH STATEMENT , mělo by to být FOR EACH ROW .
  • Protože jste již definovali oddělovač na //; musíte použít // (místo ; ) v DROP TRIGGER IF EXISTS .. prohlášení.
  • Row_Count() bude mít hodnotu 0 v Before Delete Trigger , protože ještě nebyly aktualizovány žádné řádky. Tento přístup tedy nebude fungovat.

Nyní je trik v použití Dostupné (a trvalé) na úrovni relace uživatelsky definované proměnné . Můžeme definovat proměnnou, řekněme @rows_being_deleted a později zkontrolujte, zda je již definován nebo ne.

For Each Row spustí stejnou sadu příkazů pro každý odstraňovaný řádek . Takže jen zkontrolujeme, zda proměnná relace již existuje nebo ne. Pokud tomu tak není, můžeme to definovat. V zásadě se tedy pro první řádek (který se smaže) nadefinuje, což bude přetrvávat, dokud tam bude relace.

Nyní, pokud existuje více řádků k odstranění, Trigger spustí stejnou sadu příkazů pro zbývající řádky. Ve druhém řádku by se nyní nacházela dříve definovaná proměnná a nyní můžeme jednoduše vyvolat výjimku.

Poznámka že existuje šance, že v rámci stejné relace může být spuštěno více příkazů delete. Takže před vyvoláním výjimky musíme nastavit @rows_being_deleted hodnotu zpět na null .

Bude fungovat následující:

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 :Pokus o smazání více než řádku.

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

Výsledek:

DB Fiddle Demo 2 :Pokus o smazání pouze jednoho řádku

Dotaz č. 1

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

Dotaz č. 2

SELECT * FROM `test`;

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



  1. Jak aktualizovat sloupec na základě filtru jiného sloupce

  2. Jak vytvořit tabulku s více cizími klíči a nenechat se zmást

  3. Jarní datový dotaz pro localdate vrací nesprávné položky - mínus jeden den

  4. Mapování JPA:QuerySyntaxException:foobar není namapován...