Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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;
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;
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.
–
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
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) + 1
WHERE animalname = :new.animalname;
ELSIF DELETING
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) - 1
WHERE animalname = :old.animalname;
ELSIF UPDATING
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.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.