Maison > Questions et réponses > le corps du texte
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粉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.