recherche

Maison  >  Questions et réponses  >  le corps du texte

Le déclencheur MySQL ne fonctionne pas après la suppression de la mise à jour

Désolé de poser à nouveau cette question car il y a beaucoup de choses sur le forum à ce sujet. Mais j'espère que mon problème est différent des autres. Désolé pour mon mauvais anglais.

J'ai d'abord 2 tables (table parent et table enfant) Parent (lieu)

loc_id loc_size
1 100
2 75

Enfants (Zone)

ar_id ar_loc_id ar_size
1 2 35
2 2 40

C'est mon déclencheur post-suppression.

CREATE TRIGGER after_delete_area_location
AFTER DELETE
   ON area FOR EACH ROW

BEGIN

UPDATE location SET loc_size = loc_size + old.ar_size WHERE loc_id=old.ar_loc_id

END;

Par exemple, si je souhaite supprimer ar_id = '2', alors ar_size sera mis à jour en position loc_size.

Puisque la valeur loc_size est "0", la valeur sera de 40 après l'exécution du déclencheur.

Le problème est que le déclencheur ne fonctionne pas correctement, une fois le déclencheur exécuté, loc_size n'est pas du tout mis à jour, juste la valeur "0".

Est-ce que j'ai raté quelque chose ou quelque chose se passe parce que cela ne fonctionne tout simplement pas.

S'il vous plaît, aidez-moi à résoudre ce problème. Merci beaucoup.

P粉155832941P粉155832941298 Il y a quelques jours366

répondre à tous(1)je répondrai

  • P粉639667504

    P粉6396675042024-02-04 20:57:10

    Je ne vois rien de mal à votre déclencheur. Je l'ai testé et ça marche. Pour le rendre complet, j'ai ajouté un déclencheur d'insertion sur la table 区域.

    create table location(loc_id int,loc_size int);
    create table area(ar_id int,ar_loc_id int,ar_size int);
    
    
    delimiter //
    
    CREATE TRIGGER after_insert_area_location
    AFTER insert
       ON area FOR EACH ROW
    
    BEGIN
    
    UPDATE location SET loc_size = loc_size - new.ar_size WHERE loc_id=new.ar_loc_id;
    
    -- Note: In reality, you should throw in an if statement before the UPDATE to make sure there is enough loca_size to be taken away by the ar_size.
    END//
    
    
    CREATE TRIGGER after_delete_area_location
    AFTER DELETE
       ON area FOR EACH ROW
    
    BEGIN
    
    UPDATE location SET loc_size = loc_size + old.ar_size WHERE loc_id=old.ar_loc_id;
    
    END//
    delimiter ;
    
    insert into location values(1,100),(2,75);
    
    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       75 |
    +--------+----------+
    
    select * from area;
    Empty set (0.00 sec)
    
    
    -- Test the insert
    insert into area values(1,2,35),(2,2,40);
    select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    |     2 |         2 |      40 |
    +-------+-----------+---------+
    
     select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |        0 |
    +--------+----------+
    
    -- test the delete
    delete from area where ar_id=2;
    
    select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    +-------+-----------+---------+
    
    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       40 |
    +--------+----------+

    Comme vous pouvez le voir, dans les opérations d'insertion et de suppression, les valeurs sont mises à jour en conséquence.
    -- Mise à jour à partir d'ici --

    Il s'agit de l'instruction déclencheur after_insert_area_location 的增强版本,我将在其中演示新添加的 IF 语句以保持数据完整性。请注意,SIGNAL utilisée pour générer une erreur qui agit comme un message d'avertissement et met fin à l'opération.

    -- First of all, I truncated my table so we can start from scratch.
    -- Make sure the original trigger is dropped before creating the newer one to avoid conflicts.
    
    drop trigger after_insert_area_location //
    CREATE TRIGGER after_insert_area_location
    AFTER insert
       ON area FOR EACH ROW
    
    BEGIN
    if (select loc_size from location where loc_id=new.ar_loc_id) - new.ar_size < 0 then
    signal sqlstate '77777' set message_text='You cannot take more land than you have'; -- Note: the sqlstate code and the message_text can be modified to your liking
    end if;
    UPDATE location SET loc_size = loc_size - new.ar_size WHERE loc_id=new.ar_loc_id;
    
    END//
    
    delimiter ;
    
    -- then let's populate the location table:
    insert into location values(1,100),(2,75);
    
    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       75 |
    +--------+----------+
    
    select * from area;
    Empty set (0.00 sec)
    
    -- Now we test the insert one row at a time:
     insert into area values(1,2,35);
    
     select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       40 |
    +--------+----------+
    
     select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    +-------+-----------+---------+
    
    -- now we add another row with an ar_size more than its location can afford:
    
    insert into area values(2,2,80);
    ERROR 1644 (77777): You cannot take more land than you have

    Comme vous pouvez le voir, les déclencheurs IF 语句中的 SIGNAL 语句引发了一个错误,其中包含 SQL_STATE 代码 77777 et le message : sont prédéfinis. Cela annulera les modifications apportées depuis l'insertion de la nouvelle ligne.

    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       40 |
    +--------+----------+
    
    select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    +-------+-----------+---------+

    En bref, nous pouvons utiliser des instructions IF dans les déclencheurs pour avoir un certain contrôle sur le flux de données. L'instruction SIGNAL peut être utilisée pour invoquer intentionnellement une erreur pour arrêter/annuler l'exécution d'un déclencheur et démarrer l'action d'un déclencheur. Comme mentionné ci-dessus, non seulement les instructions UPDATE 没有执行,引发触发器的 insert du déclencheur sont également annulées.

    répondre
    0
  • Annulerrépondre