I am trying to create a trigger on any insert or update on a table which holds Diseases
with animalName
and diseaseName
. I have another table, Animals
, which holds informations like the animalName
(which is a primary key; don't comment on the design as it is not mine), and the amountOfDisease
he had. I want that, upon insert, update or delete in the Diseases
table, the amount of Diseases is automatically updated.
I have a hard time understanding how I can obtain the current animalName
so that I can update his amountOfDisease
.
So far, I have this :
CREATE OR REPLACE TRIGGER update_animal_diseases
AFTER INSERT OR UPDATE OR DELETE ON Diseases
FOR EACH ROW
BEGIN
UPDATE Animals SET amountOfDisease = amountOfDisease + 1
WHERE animalName = :NEW.animalName;
END;
/
Which compile but doesn't work, as the values in Animals
never get updated on inserting something into Diseases
. I also tried this :
CREATE OR REPLACE TRIGGER update_animal_diseases
AFTER INSERT OR UPDATE ON Diseases
FOR EACH ROW
DECLARE
DiseasesCount INTEGER;
BEGIN
SELECT COUNT(*) INTO DiseasesCount
FROM Diseases
WHERE animalName = :OLD.animalName;
UPDATE Animals SET amountOfDisease = DiseasesCount WHERE animalName = :OLD.animalName;
END;
/
As you can see I also don't really understand what the :NEW and :OLD are. How can I solve my problem, which is to update an animal amountOfDisease
on any modification of the Diseases
table ?
To be clear, what I get on INSERT-ing into Diseases
is just nothing. Nothing happens as far as I can tell.
I see two possible causes.
In the first version you are always adding +1, even on delete.
Also if amountofdisease field is null on a record after adding +1 it will null anyway.
Maybe something like this should work for you.
Tables:
CREATE TABLE animals
( animalname VARCHAR2 (10),
amountofdisease NUMBER);
CREATE TABLE diseases
( animalname VARCHAR2 (10),
diseasename VARCHAR2 (20));
Trigger:
CREATE OR REPLACE TRIGGER apps.diseases_aiud1
BEFORE DELETE OR INSERT OR UPDATE
ON diseases
REFERENCING NEW AS new OLD AS old
FOR EACH ROW
DECLARE
BEGIN
IF INSERTING
THEN
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) + 1
WHERE animalname = :new.animalname;
ELSIF DELETING
THEN
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) - 1
WHERE animalname = :old.animalname;
ELSIF UPDATING
THEN
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) + 1
WHERE animalname = :new.animalname;
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) - 1
WHERE animalname = :old.animalname;
END IF;
END diseases_aiud1;
/
Note de use of :new and :old depending on the event.
Loading sample animals:
insert into animals values ('jaguar',0);
insert into animals values ('capibara',0);
insert into animals values ('fox',0);
commit;
Test 1 Insert
insert into diseases values
('jaguar','pneumonia');
insert into diseases values
('jaguar','epistaxis');
commit;
select *
from animals;
Result 1:
1 row created.
1 row created.
Commit complete.
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 2
capibara 0
fox 0
3 rows selected.
Test 2 delete:
delete from diseases
where animalname = 'jaguar' and diseasename = 'pneumonia'
;
insert into diseases values
('fox','hydrophobia');
Result 2:
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 1
capibara 0
fox 1
Test 3 Update:
update diseases
set animalname = 'capibara'
where animalname = 'fox';
Result 3:
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 1
capibara 1
fox 0
As a side note it should be recommended to write a package in order to handle this logic. Triggers are tricky, hardest to maintain and can lead to unexpected results in some scenarios.
Regards,
If I had to speculate, you don't have matching rows in Animals
for all animals in Diseases
. You can find these by doing:
select d.*
from diseases d
where not exists (select 1 from animals a where a.animal = d.animal);
If this is the case, then you should structure the database to have an explicit foreign key relationship from diseases
to animals
. This will ensure that only valid animals are in the table.
As far as trigger,
:NEW means when New record in inserted to your primary table(primary table here means a table where you sets triggers on insert) it takes always New I'd to insert record related records as per trigger in relative table (relative table means in trigger you defined to insert / update record when primary table effected. )
:OLD means in relative table it takes last inserted I'd as new id in relative table. It can be use as foriegn key in second table.
I hope it's meaning full for your question.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.