我正在尝试在包含Diseases
animalName
和diseaseName
的表格上的任何插入或更新上创建触发器。
我有另一张表Animals
,其中包含animalName
之类的信息(这是主键;不要对设计发表评论,因为它不是我的),以及{{1} } 他有。
我希望在amountOfDisease
表中插入,更新或删除时,会自动更新疾病数量。
我很难理解如何获取当前Diseases
,以便我可以更新他的animalName
。
到目前为止,我有这个:
amountOfDisease
哪些编译但不起作用,因为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;
/
中的值永远不会在将内容插入Animals
时更新。我也试过这个:
Diseases
正如你所看到的,我也不太了解:NEW和:OLD是什么。如何解决我的问题,即在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;
/
表的任何修改上更新动物amountOfDisease
?
要明确的是,我在插入Diseases
时所得到的只是一无所获。就我所知,没有任何事情发生。
答案 0 :(得分:1)
我看到两个可能的原因。
在第一个版本中,即使在删除时,您也总是添加+1。
此外,如果添加+1后,记录中的amountofdisease字段为空,则无论如何都会为空。
也许这样的事情对你有用。
表:
CREATE TABLE animals
( animalname VARCHAR2 (10),
amountofdisease NUMBER);
CREATE TABLE diseases
( animalname VARCHAR2 (10),
diseasename VARCHAR2 (20));
触发:
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;
/
注意使用:new和:old取决于事件。
装载样本动物:
insert into animals values ('jaguar',0);
insert into animals values ('capibara',0);
insert into animals values ('fox',0);
commit;
测试1插入
insert into diseases values
('jaguar','pneumonia');
insert into diseases values
('jaguar','epistaxis');
commit;
select *
from animals;
结果1:
1 row created.
1 row created.
Commit complete.
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 2
capibara 0
fox 0
3 rows selected.
测试2删除:
delete from diseases
where animalname = 'jaguar' and diseasename = 'pneumonia'
;
insert into diseases values
('fox','hydrophobia');
结果2:
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 1
capibara 0
fox 1
测试3更新:
update diseases
set animalname = 'capibara'
where animalname = 'fox';
结果3:
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 1
capibara 1
fox 0
作为旁注,应该建议编写一个包来处理这个逻辑。触发器很棘手,难以维护,并且在某些情况下可能会导致意外结果。
此致
答案 1 :(得分:0)
如果我不得不推测,Animals
中的所有动物的Diseases
中都没有匹配的行。你可以这样做:
select d.*
from diseases d
where not exists (select 1 from animals a where a.animal = d.animal);
如果是这种情况,那么您应该构建数据库,使其具有从diseases
到animals
的显式外键关系。这将确保只有有效的动物在桌子上。
答案 2 :(得分:0)
至于触发器,
:NEW表示当插入到主表中的新记录时(主表在这里表示在插入时设置触发器的表)它总是需要新的我将根据相对表中的触发器插入记录相关记录(相对表表示在触发器中)您定义为在主表受影响时插入/更新记录。)
:OLD表示在相对表中它最后插入我作为相对表中的新id。它可以用作第二表中的foriegn键
我希望这对你的问题意义重大。